我应该使用类元、类装饰器还是重写__new__方法?
这是我的问题。我想让这个类有很多属性。我要么像foo
和bar
那样一个一个写出来,要么根据我看到的一些其他例子,似乎可以用类装饰器、 metaclass(元类)或者重写__new__
方法来自动设置这些属性。不过我不太确定哪种方法才是“正确”的做法。
class Test(object):
def calculate_attr(self, attr):
# do calculaty stuff
return attr
@property
def foo(self):
return self.calculate_attr('foo')
@property
def bar(self):
return self.calculate_attr('bar')
3 个回答
1
元类是在创建新类的时候使用的,而不是在创建类的实例时。通过这种方式,你可以注册类(比如Django就是这么做的,它用元类来创建数据库中的表)。因为class
可以被看作是一个类的装饰器,所以你可以把它想象成一种特殊的指令。
3
元类的 __new__
方法并不是用来创建你所定义的类的 __new__
方法,而是用来创建这个类本身的。元类会返回一个实际的类对象。而类的实例是通过 __new__
方法返回的。
看看下面这段(疯狂的)代码:
def MyMetaClass(name, bases, dict):
print "name", name
print "bases", bases
print "dict", dict
return 7
class C('hello', 'world'):
__metaclass__ = MyMetaClass
foo = "bar"
def baz(self, qux):
pass
print "C", C
(我用一个函数代替了类作为元类。其实任何可以调用的东西都可以当作元类,但很多人选择把自己的元类写成继承自 type
的类,并重写 __new__
方法。两者之间的区别很微妙。)
它的输出是:
name C
bases ('hello', 'world')
dict {'baz': <function baz at 0x4034c844>, '__module__': '__main__', 'foo': 'bar', '__metaclass__': <function MyMetaClass at 0x40345c34>}
C 7
这样能帮助你更好地理解元类是什么吗?
你很少需要自己定义一个元类。
5
魔法是不好的。它会让你的代码变得更难理解和维护。你几乎不需要用到元类或者 __new__
这些东西。
看起来你的需求可以用相对简单的代码来实现(只需要一点点“魔法”):
class Test(object):
def calculate_attr(self, attr):
return something
def __getattr__(self, name):
return self.calculate_attr(name)