繁体   English   中英

在Python 3中使用元类重新定义__init__

[英]Redefining __init__ with metaclass in Python 3

我正在学习python 3中的元编程。我的教授确实给了我们这个练习:

编写元类法术,用于在向导中转换学生的实例。

我这样做了:

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__)

正确调用向导类__init__而不是学生类__init__ ,但创建的对象具有空的__dict__ 我哪里错了?

您的init()替换函数创建一个本地 wizard()实例,并且不返回任何内容:

def init(*args):
    wizard(args, 'fire_spell')

这是一个单独的例子, self没有被触及。

不要使用__new__ ; 产生一个新类。 您只重命名了student班,并给了它一个无效的__init__方法。

重写__call__方法以挂钩创建实例 在那里,您可以替换或忽略第一个参数,即student类对象,并在其位置使用wizard类:

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通常只接受一个参数,所以如果没有指定,则上面添加一个magic参数。

演示:

>>> student('name1')
<__main__.wizard object at 0x10f1e8198>
>>> vars(_)
{'magic': 'fire_spell', 'name': 'name1'}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM