Если у вас есть базовый класс A
и производный класс B
, вы можете сделать следующее.
void wantAnA(A myA)
{
// work with myA
}
B derived;
// work with the object "derived"
wantAnA(derived);
Теперь для метода wantAnA
нужна копия derived
, Однако объект derived
не может быть полностью скопирован, так как класс B
может изобретать дополнительные переменные-члены, которые не находятся в его базовом классе A
.
Поэтому, чтобы вызвать wantAnA
, компилятор будет «срезать» все дополнительные члены производного класса. Результатом может быть объект, который вы не хотите создавать, потому что
A
(все особые поведения класс B
теряется). Непонятно, зачем вам нужен метакласс, , вероятно, нет . Но ради упражнения давайте рассмотрим, что это происходит.
Область действия функции Python определяется следующим образом
locals > closure > globals > builtins
Никогда не будет поиск функции в пространстве имен области, где она была вызвана. Обратите внимание, что в этом случае даже определение MyClass.__init__
не будет работать, так как методы класса должны обращаться к своему пространству имен класса через атрибуты.
class SomeClass:
foo = 0
def __init__(self):
self.foo # works
foo # raises NameError
В частности, это означает, что ваш метод init
найдет fields
в теле MyMeta.__new__
, что является его закрытием.
Хотя, обратите внимание, что пространство имен класса передается в качестве четвертого аргумента методу MyMeta.__new__
, здесь attr
. Итак, вы можете найти Myclass.fields
в attr['fields']
в MyMeta.__new__
.
class MyMeta(type):
def __new__(mcs, name, bases, attr):
fields = {'foo': 0}
def init(self, **kwargs):
print('kwargs:', kwargs)
print('MyMeta.__new__.fields:', fields)
print('attr["fields"]:', attr['fields'])
attr['__init__'] = init
return type.__new__(mcs, name, bases, attr)
class Myclass(metaclass=MyMeta):
fields = {'bar': 1}
r = {'baz': 2}
c = Myclass(**r)
kwargs: {'baz': 2}
MyMeta.__new__.fields: {'foo': 0}
attr["fields"]: {'bar': 1}