开发者

Should I use a metaclass, class decorator, or override the __new__ method?

Here is my problem. I want the following class to have a bunch of property attributes. I could either write them all out like foo and bar, or based on some other examples I've seen, it looks like I could use a class decorator, a metaclass, or override the __new__ method to set the properties automagically. I'm just not sure what the "right" way to do it would be.

class Test(object):
    def calculate_attr(self, attr):
        # do calculaty stuff
        return attr开发者_JS百科

    @property
    def foo(self):
        return self.calculate_attr('foo')

    @property
    def bar(self):
        return self.calculate_attr('bar')


Magic is bad. It makes your code harder to understand and maintain. You virtually never need metaclasses or __new__.

It looks like your use case could be implemented with pretty straightforward code (with only a small hint of magic):

class Test(object):
    def calculate_attr(self, attr):
        return something

    def __getattr__(self, name):
        return self.calculate_attr(name)


A metaclass's __new__ does not become the __new__ for the class you make—it's used to make the class itself. The actual class object is returned by the metaclass. A new instance of a class is returned by __new__.

Consider the following (insane) code:

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

(I used a function instead of a class as the metaclass. Any callable can be used as a metaclass, but many people choose to right theirs as classes that inherit from type with new overrided. The differences between that an a function are subtle.)

It outputs

name C
bases ('hello', 'world')
dict {'baz': <function baz at 0x4034c844>, '__module__': '__main__', 'foo': 'bar', '__metaclass__': <function MyMetaClass at 0x40345c34>}
C 7

Does that help you better make sense of what metaclasses are?

You will very seldom need to define a metaclass of your own.


Metaclass is used when new class - not instance - is created. This way you can for example register classes (django does it and uses it for example to create tables in the database). Since class is an instruction you can think about as a decorator for a class.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜