对于考试,教授要求我写一个对项目中所有课程生效的元类,而不直接在课堂声明中声明,这可能吗?怎么样? 例如,我有以下代码:
class MetaOne(type):
def __new__(meta, classname, supers, classdict):
print('In MetaOne.new: ', classname, supers, classdict, sep='\n...')
return type.__new__(meta, classname, supers, classdict)
def __init__(Class, classname, supers, classdict):
print('In MetaOne init:', classname, supers, classdict, sep='\n...')
print('...init class object:', list(Class.__dict__.keys()))
class Eggs: pass
print('making class')
class Spam(Eggs):
data = 1
def meth(self, arg): pass
print('making instance')
X = Spam()
print('data:', X.data)
我希望输出等于以下代码的输出:
class MetaOne(type):
def __new__(meta, classname, supers, classdict):
print('In MetaOne.new: ', classname, supers, classdict, sep='\n...')
return type.__new__(meta, classname, supers, classdict)
def __init__(Class, classname, supers, classdict):
print('In MetaOne init:', classname, supers, classdict, sep='\n...')
print('...init class object:', list(Class.__dict__.keys()))
class Eggs: pass
print('making class')
class Spam(Eggs, metaclass=MetaOne):
data = 1
def meth(self, arg): pass
print('making instance')
X = Spam()
print('data:', X.data)
即使我没有直接申报,该元类也适用于我所有的课程。 我有很多关于元类的问题,但最后在他们的类的定义中总是使用metaclass = meta声明。
答案 0 :(得分:2)
您可以在模块级别编写__metaclass__ = your_metaclass
。下面定义的所有类都将使用元类。如果在类定义中再次编写__metaclass__ = type
,则可以覆盖此项。子类正在使用父类的元类。
答案 1 :(得分:0)
嗯,我很难理解你的问题。
如果Eggs
继承MetaOne
而Spam
继承Eggs
,这是否会实现您的目标?
class MetaOne(metaclass=ABCMeta):
pass
class Eggs(MetaOne):
pass
class Spam(Eggs):
pass
也许lgiordani.com提供的信息对您有用,尤其是前面链接中的以下代码块:
class FilterClass(type):
@classmethod
def __prepare__(name, bases, **kwds):
return collections.OrderedDict()
def __new__(metacls, name, bases, namespace, **kwds):
result = type.__new__(metacls, name, bases, dict(namespace))
result._filters = [
value for value in namespace.values() if hasattr(value, '_filter')]
return result
此代码块演示了如何在不使用metaclass=ABCMeta
的情况下创建元类。
您熟悉super()
吗?
class MetaOne:
def __init__(self, name):
self.name = name
class Eggs: pass
class Spam(MetaOne, Eggs):
def __init__(self, name, is_tasty):
super().__init__(name)
self.is_tasty = is_tasty
>>> s = Spam('meta', True)
>>> s
<__main__.Spam object at 0x100705b38>
>>> s.name
'meta'
>>> s.is_tasty
True
虽然使用super()
并不是真正的元类
根据您的Python版本,您可以在模块级别定义__metaclass__ = MetaOne
,这将影响该声明下面的所有类。
class MetaOne: pass
class Eggs: pass
__metaclass__ = MetaOne
class Spam: pass
class Scrambled: pass
class Fried: pass
在此用例中,Spam
,Scrambled
和Fried
的元类都将为MetaOne
。