(AttributeError:_输入_)在使用_新_魔术方法时

2024-05-04 19:40:36 发布

您现在位置:Python中文网/ 问答频道 /正文

在处理之前,我尝试使用__new__方法检查参数有效性(str),因此我执行以下操作:

class foo:

    def __new__(cls, argument):
        if not isinstance(argument, str):
            raise TypeError('argument must be str')
        print("passed __new__")

    def __init__(self, argument):
        self.argument = argument
        print("passed __init__")

    def __enter__(self):
        print("passed __enter__")

    def __exit__(self, *args):
        print("passed __exit__")

然后,当我使用with关键字调用它时,它调用__enter____exit__

with foo('test'):
    print("i am between __enter__ and __exit__, damn!")

我得到这个输出:

passed __new__
AttributeError: __enter__

我期望这个输出:

passed __new__
passed __init__
passed __enter__
i am between __enter__ and __exit__, damn!
passed __exit__

我注意到当完全删除__new__方法时;它会起作用的。为什么使用__new__会破坏这一点?即使存在__new__,我如何让它工作


Tags: 方法selfnewfooinitdefwithexit
1条回答
网友
1楼 · 发布于 2024-05-04 19:40:36

__new__必须实际创建并返回类的实例

class foo:

    def __new__(cls, argument):
        if not isinstance(argument, str):
            raise TypeError('argument must be str')
        print("passed __new__")
        return super().__new__(cls)

    def __init__(self, argument):
        self.argument = argument
        print("passed __init__")

    def __enter__(self):
        print("passed __enter__")

    def __exit__(self, *args):
        print("passed __exit__")

在原始代码中,foo.__new__返回了None,实际上None没有属性__enter__。另外,由于None不是foo的实例,对foo.__init__的隐式调用被抑制


因为footype的实例,所以调用foo('test')

type.__call__(foo, 'test')

可以想象__call__的定义如下

def __call__(cls, *args, **kwargs):
    obj = cls.__new__(*args, **kwargs)
    if isinstance(obj, cls):
        obj.__init__(*args, **kwargs)
    return obj

重写__new__意味着您希望更改实例如何创建,而重写__init__意味着您希望更改已创建实例如何初始化。在这种情况下,如果参数的类型错误,可以避免创建新实例

相关问题 更多 >