Python 为什么我的元类的行为不符合预期

Python 为什么我的元类的行为不符合预期,python,metaclass,Python,Metaclass,好吧,我开始在伏都教和Python元类的黑暗面上乱搞了,我想在进一步修改它之前让一个简单的例子工作,为什么在我执行这段代码时它不打印print语句 class Versioned(type): def __new__(cls, name, bases, dct): return type.__new__(cls, name, bases, dct) def __setattr__(cls, key, value): print "Setting

好吧,我开始在伏都教和Python元类的黑暗面上乱搞了,我想在进一步修改它之前让一个简单的例子工作,为什么在我执行这段代码时它不打印print语句

class Versioned(type):
    def __new__(cls, name, bases, dct):
        return type.__new__(cls, name, bases, dct)

    def __setattr__(cls, key, value):
        print "Setting attr %s to %s" % (key, value)
        return object.__setattr__(cls, key, value)

class Test(object):
    __metaclass__ = Versioned

    def __init__(self):
        self.a = 1
        self.b = 2

a = Test()
a.b = 31
print dir(a)

我从未真正使用过元类,但我认为你把继承和元类混为一谈了。元类用于构建实例,但它们不会隐式地向实例添加任何内容。没有理由在
测试
中导入
\uuuu setattr\uuuu
方法。要明确地添加它,您需要修改
Test
dict(
dct
)。类似于
dct[“\uuuuu setattr\uuuuuuuu”]=cls.\uuuuuu setattr\uuuuuu
。然而,它不起作用,我不明白为什么。我找到的唯一办法是:

class Versioned(type):
    def __new__(cls, name, bases, dct):
        print("BLAH")
        def __setattr__(cls, key, value):
            print("Setting attr %s to %s" % (key, value))
            return object.__setattr__(cls, key, value)
        dct["__setattr__"] = __setattr__
        return type.__new__(cls, name, bases, dct)
我希望这能有所帮助:-)


最后,这可以帮助您理解python中的元类。

我从未真正使用过元类,但我认为您将继承与元类混为一谈。元类用于构建实例,但它们不会隐式地向实例添加任何内容。没有理由在
测试
中导入
\uuuu setattr\uuuu
方法。要明确地添加它,您需要修改
Test
dict(
dct
)。类似于
dct[“\uuuuu setattr\uuuuuuuu”]=cls.\uuuuuu setattr\uuuuuu
。然而,它不起作用,我不明白为什么。我找到的唯一办法是:

class Versioned(type):
    def __new__(cls, name, bases, dct):
        print("BLAH")
        def __setattr__(cls, key, value):
            print("Setting attr %s to %s" % (key, value))
            return object.__setattr__(cls, key, value)
        dct["__setattr__"] = __setattr__
        return type.__new__(cls, name, bases, dct)
我希望这能有所帮助:-)


最后,这可以帮助您理解python中的元类。

需要理解的是,元类本身并不是一个类——它是一个可调用的,返回一个类——一个类工厂。它的作用与我们的相同

最重要的是,元类不参与所创建类的方法解析(除非您更改
)。这就是您的
版本化的原因。\uuuuu setattr\uuuuu
对您的
测试
实例不可见。所有
Versioned
所做的就是返回一个新类(类型为
Versioned
,而不是类型为
type
),该类具有相同的
名称
base
dict
类测试(对象):
块解析出的Python运行时

类本身是可调用的(通过它们的方法)。(
\uuuuu new\uuuu
用于类,而
\uuuu call\uuuuu
用于实例。)

由于类是可调用的,所以可以将类用作元类。实际上,
type
是一个类。尽管如此,您还是可以使用带有
\uuuu call\uuu
方法的实例!这两个例子是相似的,你可能想做的任何事情都可以用这两种方式来完成。(事实上,使用对象通常更简单。)

请注意,除了元类之外,Python还有许多其他元编程方法。特别是,Python>=2.6增加了对类装饰器的支持,这涵盖了元类的大多数用例,接口更简单。(您得到的不是自己创建的类,而是一个已经创建的类对象,您可以修改它。)


您可以在上看到对多种元编程方法的概述。最初的问题是“如何使内置Python容器类型线程安全?”

需要理解的是,元类本身并不是一个类——它是一个可调用的,返回一个类——一个类工厂。它的作用与我们的相同

最重要的是,元类不参与所创建类的方法解析(除非您更改
)。这就是您的
版本化的原因。\uuuuu setattr\uuuuu
对您的
测试
实例不可见。所有
Versioned
所做的就是返回一个新类(类型为
Versioned
,而不是类型为
type
),该类具有相同的
名称
base
dict
类测试(对象):
块解析出的Python运行时

类本身是可调用的(通过它们的方法)。(
\uuuuu new\uuuu
用于类,而
\uuuu call\uuuuu
用于实例。)

由于类是可调用的,所以可以将类用作元类。实际上,
type
是一个类。尽管如此,您还是可以使用带有
\uuuu call\uuu
方法的实例!这两个例子是相似的,你可能想做的任何事情都可以用这两种方式来完成。(事实上,使用对象通常更简单。)

请注意,除了元类之外,Python还有许多其他元编程方法。特别是,Python>=2.6增加了对类装饰器的支持,这涵盖了元类的大多数用例,接口更简单。(您得到的不是自己创建的类,而是一个已经创建的类对象,您可以修改它。)


您可以在上看到对多种元编程方法的概述。最初的问题是“如何使内置Python容器类型线程安全?”

您是为类本身而不是为其实例定义
\uuuu setattr\uuuu
。这将导致打印语句执行:

Test.key = value

您是为类本身而不是为其实例定义
\uuuuu setattr\uuuuu
。这将导致打印语句执行:

Test.key = value

姓“阿维拉”的你们怎么可能和多米尼加人一起上学?你们必须有一个真正开放的思想……姓氏像“阿维拉”,你们怎么可能和多米尼加人一起上学?你必须有一个真正开放的思想。。。
class MetaClass(type):
    def __new__(cls, name, bases, dict_):
        print "I am {} called with {}, {}, {}".format(cls, name, bases, dict_)
        return type.__new__(cls, name, bases, dict_)

class MetaObject(object):
    def __call__(self, name, bases, dict_):
        print "I am {} called with {}, {}, {}".format(self, name, bases, dict_)
        return type(name, bases, dict_)


class MyClass(object):
    __metaclass__ = MetaClass


class MyClass2(object):
    __metaclass__ = MetaObject()
Test.key = value