6

这是我的问题。我希望下面的类有一堆属性。我可以像fooand一样将它们全部写出来bar,或者基于我见过的其他一些示例,看起来我可以使用类装饰器、元类或重写__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')
4

3 回答 3

5

魔术很糟糕。它使您的代码更难理解和维护。您几乎不需要元类或__new__.

看起来您的用例可以用非常简单的代码来实现(只有一点点魔法):

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

    def __getattr__(self, name):
        return self.calculate_attr(name)
于 2010-03-24T00:01:18.690 回答
2

元类__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自新覆盖的类。a 函数之间的差异是微妙的。)

它输出

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

这是否有助于您更好地理解元类什么?

很少需要定义自己的元类。

于 2010-03-23T21:33:48.443 回答
1

创建新类而不是实例时使用元类。通过这种方式,您可以例如注册类(django 会这样做并使用它例如在数据库中创建表)。由于class是一个指令,您可以将其视为类的装饰器。

于 2010-03-23T21:34:22.643 回答