最近剛接觸python的元類,網絡上有比較詳細的介紹,這裏是在看Django時候發現一點關於元類的應用,作個筆記。python
from django.utils import six class A(type): def __new__(cls, name, parents, attrs): return type.__new__(cls, name, parents, attrs) class C(six.with_metaclass(A)): pass
建立C類的時候,他會先調用__metaclass__屬性裏面的東西。上面C類中的代碼能夠是django
class C(object): __metaclass__ = A
def with_metaclass(meta, *bases): """Create a base class with a metaclass.""" # This requires a bit of explanation: the basic idea is to make a dummy # metaclass for one level of class instantiation that replaces itself with # the actual metaclass. class metaclass(meta): def __new__(cls, name, this_bases, d): return meta(name, bases, d) return type.__new__(metaclass, 'temporary_class', (), {})
若是咱們須要作一些小動做,能夠在這裏下手。
網絡
那麼如今就在A類繼承一個B類,在加上幾個新的變量。ssh
from django.utils import six class A(type): def __new__(cls, name, parents, attrs): attrs['name'] = 'sora' attrs['sex'] = 'man' name = 'Hello' parents = (B,) return type.__new__(cls, name, parents, attrs) class B(object): a = 123456 class C(six.with_metaclass(A)): pass c = C() print dir(c) print c.name print c.__class__ print c.a
輸出結果:ide
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'name', 'sex']學習
soraui
<class '__main__.Hello'>this
123456idea
parents是父類,attrs是一個字典,注意的是,attrs不能寫成{'name':'sora','sex':',man'}這樣是不對的.name是建立的類名字.code
這裏就是一些簡單的一些應用了,在Django裏面,常常要用到class Meta這個東西,Django相關的tastypie裏面也有,好比Resource類,看了一下源代碼學習了下.
#coding:utf-8 from django.utils import six class B(object): opt_1 = 1 opt_2 = 2 opt_3 = 3 def __new__(cls, meta=None): overrides = {} if meta: for override_name in dir(meta): if not override_name.startswith('_'): overrides[override_name] = getattr(meta,override_name) return object.__new__(type(b'B',(cls,),overrides)) class A(type): def __new__(cls, name, bases, attrs): new_class = super(A,cls).__new__(cls,name,bases,attrs) # new_class = type.__new__(cls, name, bases, attrs) ops = getattr(new_class,'Options',None) new_class._opt = B(ops) return new_class class C(six.with_metaclass(A)): def show_opt(self): opt = self._opt print 'opt_1:',opt.opt_1 print 'opt_2:',opt.opt_2 print 'opt_3:',opt.opt_3 class D(C): class Options: opt_1 = 5 d = D() d.show_opt()
輸出結果:
opt_1: 5
opt_2: 2
opt_3: 3
Django裏面是class Meta,這裏換了下名字。