【发布时间】:2022-06-11 21:27:17
【问题描述】:
我有许多类继承了一个共同的类。我需要父类来跟踪在类级别定义的一堆依赖/关系。比如:
class Meta(type):
ALLDEPENDENCIES = {}
def __new__(meta, name, bases, attrs):
if "DEPENDENCIES" in attrs.keys():
for key, value in attrs.items():
if key == "DEPENDENCIES":
meta.ALLDEPENDENCIES.update(attrs["DEPENDENCIES"])
return type.__new__(meta, name, bases, attrs)
class DataTable(DataFrameWrapper, metaclass=Meta):
pass
class Foo(DataTable):
DEPENDENCIES = {"a":1}
class Bar(DataTable):
DEPENDENCIES = {"b":2}
本质上,当我创建新类(Foo、Bar、Baz...)时,它们中的每一个都有一个字典。我需要合并每个字典中的信息。所以我使用的是元类,如上所示。每个类都作为一个 DEPENDENCIES 属性,我将所有这些都收集到元类中定义的 ALLDEPENDENCIES 属性中。
如果我这样做,它似乎可以正常工作:
import Foo, Bar
print(Foo.ALLDEPENDENCIES)
>> {"a":1, "b":2}
print(Bar.ALLDEPENDENCIES)
>> {"a":1, "b":2}
但是,当使用 obj 实例时,缺少 ALLDEPENDENCIES 属性:
f = Foo()
b = Bar()
print(f.ALLDEPENDENCIES)
print(b.ALLDEPENDENCIES)
属性错误 - 没有 ALLDEPENDENCIES。
我认为元类中定义的类属性可以从实例中的 self.myattribute 访问,就像 DEPENDENCIES 一样。我做错了什么?
【问题讨论】:
-
这并不完全是一个骗局,但这里有一个很好的(虽然有点老)讨论可能会有所帮助:methods of metaclasses on class instances
-
"我认为元类中定义的类属性可以从实例中的 self.myattribute 访问" 不,实例在 类命名空间 中查找属性,而不是元类命名空间。注意,类是元类的实例,所以它们在它们的(元)类命名空间中查找属性
-
@juanpa.arrivillaga 啊,我明白了。但是我可以从实例访问该命名空间吗?理想情况下,不必在我可能需要查找的任何地方导入 Foo ?还是使用元类是一种完全错误的方法?虽然这对我来说似乎很合适。
-
FWIW,
__init_subclass__方法可能更好地服务于这个用例。这可以让你避免编写元类。
标签: python metaclass class-attributes