I have a number of classes that inherit a common one. I need the parent class to keep track of a bunch of dependencies/relationships that are defined at the class level. Something like:
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}
So essentially, as I create new classes (Foo, Bar, Baz...) each of them has a dictionary. I need to merge the info from each dictionary. So I'm using the metaclass, as shown above. Each class as an DEPENDENCIES attribute, and I'm gathering all of those into the ALLDEPENDENCIES attribute defined in the metaclass.
If I do this, it seems to work alright:
import Foo, Bar
print(Foo.ALLDEPENDENCIES)
>> {"a":1, "b":2}
print(Bar.ALLDEPENDENCIES)
>> {"a":1, "b":2}
However, when working if obj instances, the ALLDEPENDENCIES attributes is missing:
f = Foo()
b = Bar()
print(f.ALLDEPENDENCIES)
print(b.ALLDEPENDENCIES)
Attribute error - there is no ALLDEPENDENCIES.
I thought that the class attribute defined in the metaclass would be accessible from self.myattribute in the instances, just like DEPENDENCIES is. What am I doing wrong?
Meta describes how
to create class but not what
class that will be.
Meta
!= Parent
with inherited attributes
So you have to pass proper attributes into new class:
class Meta(type):
_a = {}
def __new__(meta, name, bases, attrs):
if "d" in attrs:
meta._a.update(attrs["d"])
attrs["a"] = meta._a
return type.__new__(meta, name, bases, attrs)
class Data:
pass
class DataTable(Data, metaclass=Meta):
pass
class Foo(DataTable):
d = {"a":1}
class Bar(DataTable):
d = {"b":2}
f = Foo()
print(Foo.a)
print(f.a)
{'a': 1, 'b': 2}
{'a': 1, 'b': 2}