我有课;我们称它为 Foo
。它有一个 key_type
类属性,其中包含一个类型:
class Key: pass
class Foo:
key_type = Key
我想在初始化 (*) 和更改时在键类型上运行一些方法。
所以我将 key_type
设为元类中的一个属性:
class Key: pass
class OtherKey: pass
class MetaFoo(type):
_key_type = None
@property
def key_type(cls):
return cls._key_type
@key_type.setter
def key_type(cls, value):
print(f'Setting key_type to {value}')
cls._key_type = value
class Foo(metaclass=MetaFoo):
key_type = Key
if __name__ == "__main__":
print(f"Foo's key type: {Foo.key_type}")
Foo.key_type = OtherKey
print(f"Foo's key type: {Foo.key_type}")
输出:
Foo's key type: None
Setting key_type to <class '__main__.OtherKey'>
Foo's key type: <class '__main__.OtherKey'>
似乎元类中 _key_type
的定义覆盖了主类中 key_type
的定义。但最重要的是,未使用 Key
类型调用 setter。
预期输出:
Setting key_type to <class '__main__.Key'>
Foo's key type: <class '__main__.Key'>
Setting key_type to <class '__main__.OtherKey'>
Foo's key type: <class '__main__.OtherKey'>
(*) 我也希望它在初始化时发生的原因是 Foo 可以继承自。我想知道(在 MetaFoo 或 Foo 中)子类是否使用不同的 key_type
。
最佳答案
class Foo
中key_type
的定义实际上是在第三个参数(dict)中加入了键值对,用于MetaFoo<的初始化
,它不会做任何其他事情。
因此,您可以操纵 MetaFoo
的初始化来显式调用您的 setter 方法。这可以通过覆盖元类的 __init__
方法来完成:
class Key: pass
class OtherKey: pass
class MetaFoo(type):
_key_type = None
@property
def key_type(cls):
return cls._key_type
@key_type.setter
def key_type(cls, value):
print(f'Setting key_type to {value}')
cls._key_type = value
def __init__(self, name, bases, kw):
super(MetaFoo, self).__init__(name, bases, kw)
for key, val in kw.items():
setattr(self, key, val)
class Foo(metaclass=MetaFoo):
key_type = Key
if __name__ == "__main__":
print(f"Foo's key type: {Foo.key_type}")
Foo.key_type = OtherKey
print(f"Foo's key type: {Foo.key_type}")
输出:
Setting key_type to <class '__main__.Key'>
Foo's key type: <class '__main__.Key'>
Setting key_type to <class '__main__.OtherKey'>
Foo's key type: <class '__main__.OtherKey'>
关于python - 声明类属性时如何触发setter?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55960722/