python - 声明类属性时如何触发setter?

标签 python

我有课;我们称它为 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 Fookey_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/

相关文章:

python打印正则表达式匹配产生空列表

Python C++ 模块无法读取由 Windows 上的 Python 程序创建的文件

python - 可用于制作英语词典的数据结构

python - 在 Django 中收集来自第三方应用程序的消息

python - 使用 pool.map() 时的全局字典 python

python - 如何在Python中读取Excel表格中的数据?

Python 3.3 - 从列表和 .txt 中读取多项选择然后评分

python - unicodedata.normalize(form, unistr) 是如何工作的?

python - PyLDAvis 可视化与生成的主题不一致

python - 使用 Airflow 将 mysql 数据加载到 bigquery 的 dag 出现 "Invalid arguments passed"错误