类构造函数能够使用相同类对象的实例进行init

时间:2015-10-14 14:21:52

标签: python class init self

python可以创建一个可以使用相同类对象的实例初始化的类吗?

我试过这个:

class Class(): 

    def __init__(self,**kwargs):

        print self

        self = kwargs.get('obj',self)

        print self

        if not hasattr(self,'attr1'):
            print 'attr1'
            self.attr1  = kwargs.pop('attr1',[])
        if not hasattr(self,'attr2'):
            print 'attr2'
            self.attr2 = kwargs.pop('attr2',[])

        print self

        self.attr1 = kwargs.pop('attr1',self.attr1)
        self.attr2 = kwargs.pop('attr2',self.attr2)
        print self.attr1
        print self.attr2

如果我创建一个新实例,则没有问题:

inst = Class(attr1=[1,2,3])
print inst
print inst.attr1,inst.attr2

输出结果为:

<__main__.Class instance at 0x7f2025834cf8>  
<__main__.Class instance at 0x7f2025834cf8>  
attr1  
attr2  
<__main__.Class instance at 0x7f2025834cf8>  
[1, 2, 3]  
[]  
<__main__.Class instance at 0x7f2025834cf8>  
[1, 2, 3]  []

但是,如果我使用实例inst创建一个新实例:

inst2 = Class(obj=inst)
print inst2
print inst2.attr1,inst2.attr2

输出结果为:

<__main__.Class instance at 0x7f202584b7e8>  
<__main__.Class instance at 0x7f2025835830>  
<__main__.Class instance at 0x7f2025835830>  
[1, 2, 3]  
[]  
 <__main__.Class instance at 0x7f202584b7e8>  
AttributeError                            Traceback (most recent call last)  
<ipython-input-228-29c9869a9f4d> in <module>()  
       1 inst2 = Class(obj=inst)  
       2 print inst2  
 ----> 3 print inst2.attr1,inst2.attr2  

 AttributeError: Class instance has no attribute 'attr1'  

我处理问题,但我不知道如何解决它:

  • 在第一种情况下,实例地址始终相同(“内部”和“外部”类)
  • 在第二种情况下:

    • “在课堂内”:
    • init调用在新地址创建新实例
    • 然后将self设置为上一个实例并更改地址:确定
    • self已有属性attr1atrr2:确定

    • 但在课堂“外面”:

    • inst2具有init的地址,没有属性!

有什么问题?如何在Python中解决影响问题? 这样做是否很好?

2 个答案:

答案 0 :(得分:1)

不确定您要尝试实现的目标,但从技术上讲,您的错误就在这里:

    self = kwargs.get('object',self)

self没有什么神奇之处,它只是一个函数参数,并且作为一个局部变量,所以在函数中重新绑定它只会产生本地名{{1} }指向函数范围内的另一个对象 。它不会影响当前实例(方法包装器传递给self的实例),它只会使__init__成为self的别名。

如果您要将属性从object复制到object,则必须明确地执行此操作:

self

哦,是的:Python是高级语言,没有什么比#34;解决情感&#34; - 你所拥有的只是引用对象的名称(实际上,name =&gt;对象映射)。名称只是一个名称,对象实际存在的位置不是您的顾虑。

答案 1 :(得分:-1)

  • 感谢上面的评论,我理解了两件事:

    • self只是一个局部变量,它不是类实例
    • _init_它是一个用于从其他对象
    • 初始化实例的类内置方法
  • 因此,如果我希望能够从现有实例初始化新的类实例,我只需要创建一个调用_init_的“初始化程序”方法:

    class Class(): 
    
    
        def __init__(self,**kwargs):
    
            self.attr1 = kwargs.pop('attr1',[])
            self.attr2 = kwargs.pop('attr2',[])
    
        def Class(self,**kwargs):
    
            return Class(attr1 = kwargs.pop('attr1',self.attr1),\
                         attr2 = kwargs.pop('attr2',self.attr2))
    

并像这样使用它:

inst = Class(attr1=[1,2,3])
print inst
print inst.attr1,inst.attr2

输出:

<__main__.Class instance at 0x7eff842d5368>
[1, 2, 3] []
inst2 = inst.Class(attr2=[12,11])
print inst2
print inst2.attr1,inst2.attr2

输出:

<__main__.Class instance at 0x7eff842d56c8>
[1, 2, 3] [12, 11]