【发布时间】:2020-11-20 23:14:57
【问题描述】:
我试图使用 Python 内置的 setattr 为类设置类型属性。我已经在类型中声明了__new__ 和__init__ 方法,以查看它们的参数是什么,令人惊讶的是,它们并没有被绑定到接收类实例。我已经阅读了有关setattr 和描述符的Python 文档,并且我在解释器中执行了一些测试,但我还没有找到将类型的__new__ 或__init__ 方法绑定到类实例的方法。
这是我一直在玩弄的代码片段:
T = type("T", (object,), {"__new__": lambda cls: print(f"T.__new__: {cls}") or object.__new__(cls), "__init__": lambda self: print(f"T.__init__: {self}")})
T()
# T.__new__: <class '__main__.T'>
# T.__init__: <__main__.T object at 0x7f970b667c10>
# <__main__.T object at 0x7f970b667c10>
class A:
pass
setattr(A, "T", T)
A.T()
# T.__new__: <class '__main__.T'>
# T.__init__: <__main__.T object at 0x7f970b6675e0>
# <__main__.T object at 0x7f970b6675e0>
A().T()
# T.__new__: <class '__main__.T'>
# T.__init__: <__main__.T object at 0x7f970b667ee0>
# <__main__.T object at 0x7f970b667ee0>
基本上我想知道如何让 T 在 __new__ 或 __init__ 方法中接收 A 的实例。我相信我没有完全理解 setattr 的实际工作原理,并且我在滥用它,或者完成此行为的方式与 setattr 根本无关。
PS.:将 T 声明为常规类不会改变任何事情,而声明 T::__get__ 也不会改变任何事情。
【问题讨论】:
-
这似乎是XY problem。您在询问
setattr,但您的实际目标似乎是A().T()的绑定行为(您希望T类绑定到它正在查找的A实例)。是对的吗?如果您真的详细了解setattr,我不想在关于绑定行为的答案的第一段中忽略setattr。 -
@Blckknght 你是对的,我会纠正的。
-
它像任何其他对象一样工作。在其类命名空间中具有另一种类型的类型没有什么特别之处。你想要的根本不会自动发生。您可以通过定义一个作为描述符的元类来完成它,但是它将涉及关于如何/何时使用描述符的相当神秘的方面。老实说,这似乎不值得。 您要解决的实际问题是什么?您是否希望它像 Java 非静态嵌套类一样工作?
-
setattr与此处无关。setattr(A, "T", T)完全等同于A.T = T。此外,使用type构造函数并不真正相关。同样,如果您使用类定义语句,它的工作方式相同。 -
@juanpa.arrivillaga 我只想在调用
a.T()时在T初始化中访问A实例a,以避免a.T(a)。一旦我知道如何做到这一点,它可能就不值得了,尽管我仍然想知道如何做到这一点。目前在 Google 的首页找不到。