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