Вот исполняемый код, который работает в Python 2.7, но приводит к ошибке в Python 3.6:
import six
class AMeta(type):
def __new__(cls, name, bases, attrs):
module = attrs.pop('__module__')
new_attrs = {'__module__': module}
classcell = attrs.pop('__classcell__', None)
if classcell is not None:
new_attrs['__classcell__'] = classcell
new = super(AMeta, cls).__new__(
cls, name, bases, new_attrs)
new.duplicate = False
legacy = super(AMeta, cls).__new__(
cls, 'Legacy' + name, (new,), new_attrs)
legacy.duplicate = True
return new
@six.add_metaclass(AMeta)
class A():
def pr(cls):
print('a')
class B():
def pr(cls):
print('b')
class C(A,B):
def pr(cls):
super(C, cls).pr() # not shown with new_attrs
B.pr(cls)
print('c') # not shown with new_attrs
c = C()
c.pr()
# Expected result
# a
# b
# c
Я получаю следующую ошибку:
Traceback (most recent call last):
File "test.py", line 28, in <module>
class C(A,B):
TypeError: __class__ set to <class '__main__.LegacyC'> defining 'C' as <class '__main__.C'>
C наследуется отОбъект, сгенерированный метаклассом AMeta.Это классы тестов, и цель AMeta состоит в том, чтобы выполнить все тесты с двумя разными папками: одна по умолчанию и старая.
Я нашел способ устранить эту ошибку, удалив classcell от attrs, затем возвращается new = super (AMeta, cls). new (cls, name, base, attrs) (не new_attrs ) но это кажется неправильным, и если это так, я хотел бы знать, почему.
Цель new_attrs возникла в результате этого ТАКого вопроса или документация , где говорится в основном обратное: при изменении атрибутов обязательно сохраняйте classcell , поскольку он устарел в Python 3.6 и приведет к ошибке в Python 3.8.Обратите внимание, что в этом случае он удаляет определение pr, потому что они не были переданы new_attrs , поэтому печатает 'b' вместо 'abc', но это не имеет отношения к этой проблеме.
Есть ли способ вызвать несколько super (). new внутри new метакласса AMeta, а затем вызвать их из класса C, унаследованного от класса, наследующего A?
Без вложенного наследования ошибка не появляется, как это:
import six
class AMeta(type):
def __new__(cls, name, bases, attrs):
new = super(AMeta, cls).__new__(
cls, name, bases, attrs)
new.duplicate = False
legacy = super(AMeta, cls).__new__(
cls, 'Duplicate' + name, (new,), attrs)
legacy.duplicate = True
return new
@six.add_metaclass(AMeta)
class A():
def pr(cls):
print('a')
a = A()
a.pr()
# Result
# a
Тогда, может быть, роль А - сделать что-то, чтобы это исправить?
Спасибо заранее,