gpt4 book ai didi

python - 为什么我的元类没有按预期表现

转载 作者:太空宇宙 更新时间:2023-11-04 10:50:50 24 4
gpt4 key购买 nike

好吧,我开始用元类来处理巫术和 Python 的阴暗面,我想在进一步修改它之前让一个简单的例子工作,为什么当我执行这段代码时它不打印打印语句,

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)

最佳答案

需要理解的是,元类本身并不是一个——它是一个返回类的可调用对象——一个类工厂。它的用途与 type(__name__, __bases__, __dict__) 相同.

>>> type('myclass', (), {})
<class '__main__.myclass'>

当你定义__metaclass__时,你只是overriding the default class factory for that specific class or module .例如,这是一个元类:

def setattr_logging_class(name, bases, dict_):
"""I am a metaclass"""
def __setattr__(self, k, v):
print "{} set attribute {} to {}".format(self, k, v)
super(self.__class__, self).__setattr__(k, v)
dict_['__setattr__'] = __setattr__
cls = type(name, bases, dict_)
return cls

class MyClass(object):
__metaclass__ = setattr_logging_class
def __init__(self):
self.a = 1

obj = MyClass()
obj.b = 2

print obj.__dict__

最重要的是,元类不参与创建类的方法解析(除非您更改bases)。这就是为什么您的 Versioned.__setattr__ 对您的 Test 实例不可见。 Versioned 所做的只是返回一个具有相同 name 的新类(类型为 Versioned 而不是类型 type), basesdict_ Python 运行时从您的 class Test(object): block 中解析出来。

类本身是可调用的(通过它们的 __new__ 方法)。 (__new__ 用于类,而 __call__ 用于实例。)

class MyClass(object):
def __new__(cls_self, *args, **kwargs):
print "I am {} called with {} and {}".format(cls_self, args, kwargs)
return None

myobj = MyClass(1,2,3,a=4,b=5,c=6)
print myobj # == None

由于类是可调用的,您可以将类用作元类。其实type就是一个类。虽然,您也可以使用带有 __call__ 方法的实例!这两个示例很相似,没有什么是您想做却做不到的以任何一种方式完成。 (事实上​​,使用对象通常更直接。)

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()

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

您可以在 this stackoverflow answer I recently wrote 查看对多种元编程方法的调查。 .最初的问题是“如何使内置 Python 容器类型成为线程安全的?”

关于python - 为什么我的元类没有按预期表现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14071628/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com