使用 Python 中的元类重新定义 __init__ 3
Redefining __init__ with metaclass in Python 3
我正在学习元编程 python 3. 我的教授给了我们这个练习:
编写 metaclass 法术,在巫师中转换学生实例。
我这样做了:
class Spell(type):
def __new__(cls, classname, supers, cls_dict):
cls_dict['__init__'] = Spell.toWizard()
cls_dict['__qualname__'] = 'wizard'
return type.__new__(cls, 'wizard', supers, cls_dict)
@staticmethod
def toWizard():
def init(*args):
wizard(args, 'fire_spell')
return init
class student(metaclass=Spell):
def __init__(self, name):
self.name = name
class person():
def __init__(self, name):
self.name = name
class wizard(person):
def __init__(self, name, magic):
self.magic = magic
super().__init__(name)
if __name__ == '__main__':
s = student('name1')
print(s.__dict__)
s = student('name2')
print(s.__dict__)
向导 class __init__
被正确调用而不是学生 class __init__
,但是创建的对象有一个空的 __dict__
。我哪里错了?
您的 init()
替换函数会创建一个 local wizard()
实例,并且不会 return 任何东西:
def init(*args):
wizard(args, 'fire_spell')
那是一个单独的实例,self
没有被触及。
不要使用__new__
;产生一个新的 class。你只是重命名了 student
class 并给它一个无效的 __init__
方法。
覆盖 __call__
方法以挂钩创建 实例 。您可以在那里替换或忽略第一个参数,即 student
class 对象并使用 wizard
class 代替它:
class Spell(type):
def __call__(cls, *args, **kwargs):
# ignore the cls argument, return a wizard instead
if 'magic' not in kwargs and len(args) < 2:
# provide a default magic value
kwargs['magic'] = 'fire_spell'
return wizard(*args, **kwargs)
因为student
通常只接受一个参数,所以如果指定none,上面会添加一个magic
参数。
演示:
>>> student('name1')
<__main__.wizard object at 0x10f1e8198>
>>> vars(_)
{'magic': 'fire_spell', 'name': 'name1'}
我正在学习元编程 python 3. 我的教授给了我们这个练习:
编写 metaclass 法术,在巫师中转换学生实例。
我这样做了:
class Spell(type):
def __new__(cls, classname, supers, cls_dict):
cls_dict['__init__'] = Spell.toWizard()
cls_dict['__qualname__'] = 'wizard'
return type.__new__(cls, 'wizard', supers, cls_dict)
@staticmethod
def toWizard():
def init(*args):
wizard(args, 'fire_spell')
return init
class student(metaclass=Spell):
def __init__(self, name):
self.name = name
class person():
def __init__(self, name):
self.name = name
class wizard(person):
def __init__(self, name, magic):
self.magic = magic
super().__init__(name)
if __name__ == '__main__':
s = student('name1')
print(s.__dict__)
s = student('name2')
print(s.__dict__)
向导 class __init__
被正确调用而不是学生 class __init__
,但是创建的对象有一个空的 __dict__
。我哪里错了?
您的 init()
替换函数会创建一个 local wizard()
实例,并且不会 return 任何东西:
def init(*args):
wizard(args, 'fire_spell')
那是一个单独的实例,self
没有被触及。
不要使用__new__
;产生一个新的 class。你只是重命名了 student
class 并给它一个无效的 __init__
方法。
覆盖 __call__
方法以挂钩创建 实例 。您可以在那里替换或忽略第一个参数,即 student
class 对象并使用 wizard
class 代替它:
class Spell(type):
def __call__(cls, *args, **kwargs):
# ignore the cls argument, return a wizard instead
if 'magic' not in kwargs and len(args) < 2:
# provide a default magic value
kwargs['magic'] = 'fire_spell'
return wizard(*args, **kwargs)
因为student
通常只接受一个参数,所以如果指定none,上面会添加一个magic
参数。
演示:
>>> student('name1')
<__main__.wizard object at 0x10f1e8198>
>>> vars(_)
{'magic': 'fire_spell', 'name': 'name1'}