在__init__参数列表中初始化对象,以返回相同的实例作为默认值。

8 浏览
0 Comments

在__init__参数列表中初始化对象,以返回相同的实例作为默认值。

给定以下示例代码:

class Foo:
    def __init__(self):
        return
class Bar:
    def __init__(self, foo = Foo()):
        print(foo)
bar1 = Bar()
bar2 = Bar()
print(bar1)
print(bar2)

输出如下:

<__main__.Foo object at 0x000002A989A2E9B0>
<__main__.Foo object at 0x000002A989A2E9B0>
<__main__.Bar object at 0x000002A989A2EA20>
<__main__.Bar object at 0x000002A989A2EA90>

让两个Foo实例都是相同的是出乎意料的。我希望每次创建一个Bar()对象时,都能得到一个独立的Foo对象。

如何修改我的示例,以便每次调用Bar()都会创建自己独立的Foo对象?我需要使用__new__吗?

0
0 Comments

在上述代码中,定义了一个名为Foo的类和一个名为Bar的类。Bar类的构造函数__init__有一个参数foo,默认值为None。如果foo的值为None,则将foo赋值为一个新的Foo对象。

问题的原因是,每次实例化Bar类的对象时,会调用__init__函数,如果没有传入foo的值,则会创建一个新的Foo对象。因此,bar1和bar2的foo属性指向不同的Foo对象。

解决方法是在类的定义中,将默认值设为一个可变对象,例如将foo的默认值设为一个空的列表[]。这样,每次实例化Bar类的对象时,如果没有传入foo的值,会使用同一个可变对象作为默认值,从而保证bar1和bar2的foo属性指向同一个对象。

以下是修改后的代码示例:

class Bar:
    def __init__(self, foo = []):
        if not foo:
            foo.append(Foo())
        print(foo)
bar1 = Bar()
bar2 = Bar()
print(bar1)
print(bar2)

或者使用attr库来解决这个问题,具体的代码如下所示:

import attr
class Bar(object):
    foo = attr.ib(default=attr.Factory(list))
bar1 = Bar()
bar2 = Bar()
print(bar1.foo)
print(bar2.foo)

这样修改后,bar1和bar2的foo属性指向同一个空列表对象。

0