毎日Learning

学んだことを共有します

無名クラスの作り方

Djangoのsitemapsフレームワーク sitemaps フレームワーク — Django v1.0 documentation を使って、sitemap.xmlを作った。

その際、サイトマップインデックスを生成したのだが、サイトマップインデックスのリンク先の各サイトマップ内で、それぞれ異なる処理をさせたかったので、同じような処理だが、やや違う処理をするクラスをたくさん作る必要があった。

クラスをたくさん作るんじゃなく、インスタンス化する際に引数でクラスの状態を変えるような実装も考えたが、Djangoのsitemapsフレームワークにそのまま流したかったので、無名クラスをたくさん作る方法を試してみた。

無名クラスを使わない場合は、以下のようなコードになる。

from django.contrib.sitemaps import Sitemap

## このクラスをたくさん作る
class HogeSitemap1(Sitemap):
    changefreq = "daily"
    priority = 0.5

    def items(self):
        return Hoge.objects.filter(name="hoge1") # ここだけが変わる

    def lastmod(self, obj):
        return obj.update_date

    def location(self, obj):
        return "/hoge/%s/" % (obj.id,)

class HogeSitemap2(Sitemap):
    changefreq = "daily"
    priority = 0.5

    def items(self):
        return Hoge.objects.filter(name="hoge2") # ここだけが変わる

    def lastmod(self, obj):
        return obj.update_date

    def location(self, obj):
        return "/hoge/%s/" % (obj.id,)

...

冗長でめんどい。。。

無名クラスを使った場合は、以下のようになる。

from django.contrib.sitemaps import Sitemap

def get_class(i, hoge):
    return type("HogeSitemap%d" % (i+1), (Sitemap,), {
        "changefreq": "daily",
        "proproty": 0.5,
        "items": lambda self: Hoge.objects.filter(name=hoge), # ここで変数を受けとる
        "lastmod": lambda self, obj: obj.update_date,
        "location": lambda self, obj: "/hoge/%s/" % (obj.id,),
    })

[get_class(i, hoge) for i, hoge in enumerate(["hoge1", "hoge2"])]

>> [<class 'HogeSitemap1'>, <class 'HogeSitemap2'>]

良い勉強になった。