python类初始化作用_Python中的类初始化

本文探讨了Python中类的初始化,包括`__init__`方法的作用。作者通过示例代码展示了没有`__init__`时如何默认创建实例变量,并解释了类变量和实例变量的区别。此外,还讨论了在类中直接定义变量和在`__init__`中初始化实例变量之间的差异,以及这如何影响内存中的对象引用。
摘要由CSDN通过智能技术生成

我发现有些类包含一个__init__函数,有些则没有。我对以下描述的内容感到困惑。

这两段代码有什么区别:

classTest1(object):i=1

classTest2(object):def__init__(self):self.i=1

我知道这两个类创建的结果或任何实例以及获取其实例变量的方式几乎相同。但是,当我们不__init__为类定义函数时,在幕后是否存在Python的某种“默认”或“隐藏”初始化机制?以及为什么我不能以这种方式编写第一个代码:

classTest1(object):self.i=1

那是我的问题。非常感谢你!

非常感谢Antti Haapala!您的回答使我对我的问题有了进一步的了解。现在,我知道它们的不同之处在于,一个是“类变量”,另一个是“实例变量”。但是,当我进一步尝试时,又遇到了另一个令人困惑的问题。

这就是它。我创建了2个新类来了解您的发言:

classTest3(object):class_variable=[1]def__init__(self):self.instance_variable=[2]classTest4(object):class_variable=1def__init__(self):self.instance_variable=2

就像您在回答第一个问题时所说的那样,我理解class_variable是类的通用“类变量”,应该通过引用内存中的相同位置来传递或更改它。并且instance_variable将为不同的实例分别创建。

但是,正如我尝试过的那样,您所说的对于Test3的实例是正确的,它们都共享相同的内存。如果我在一个实例中对其进行更改,则其值会随我调用的位置而改变。

但这对于Test4的实例并非如此。如果不是INT在TEST4类也通过引用改变?

i1 = Test3()

i2=Test3()>>>i1.i.append(2)>>>i2.i[1,2]j1=Test4()j2=Test4()>>>j1.i=3>>>j2.i1

这是为什么?是否在默认情况下不更改原始“Test4.i”的情况下创建一个名为“i”的“实例变量”?但是“append”方法只处理“类变量”吗?

再次感谢您向Python新手详尽地解释了最无聊的基本概念。我真的很感激!

解决方案

在python中,实例属性(例如self.i)存储在实例字典(i.__dict__)中。类主体中的所有变量声明都存储为类的属性。

从而

classTest(object):i=1

相当于

classTest(object):passTest.i=1

如果__init__未定义方法,则新创建的实例通常以空实例字典开头,这意味着未定义任何属性。

现在,当Python执行get属性时(在print(instance.i)操作中,它首先查找i在实例上设置的名为属性)。如果失败,则改为i查找该属性type(i)(即class attributei)。

因此,您可以执行以下操作:

classTest:i=1t=Test()print(t.i)# prints 1t.i+=1print(t.i)# prints 2

但这实际上是:

>>>classTest(object):...i=1...>>>t=Test()>>>t.__dict__{}>>>t.i+=1>>>t.__dict__{'i':2}

i新创建的属性完全没有t!因此,在t.i += 1该.i被查找的Test类阅读,但新的值被设置成t。

如果您使用__init__:

>>>classTest2(object):...def__init__(self):...self.i=1...>>>t2=Test2()>>>t2.__dict__{'i':1}

新创建的实例t2将已经设置了属性。

现在,在诸如不变值的情况下,int并没有太大的区别。但是,假设您使用了一个列表:

classClassHavingAList():the_list=[]

classInstanceHavingAList()def__init__(self):self.the_list=[]

现在,如果您同时创建两个实例:

>>>c1=ClassHavingAList()>>>c2=ClassHavingAList()>>>i1=InstanceHavingAList()>>>i2=InstanceHavingAList()>>>c1.the_listisc2.the_listTrue>>>i1.the_listisi2.the_listFalse>>>c1.the_list.append(42)>>>c2.the_list[42]

c1.the_list并c2.the_list指向内存中完全相同的列表对象,而i1.the_list和i2.the_list是不同的。修改c1.the_list外观,就好像它们c2.the_list也改变一样。

这是因为attribute本身未设置,只是被读取。的c1.the_list.append(42)行为与

getattr(c1,'the_list').append(42)

That is, it only tries read the value of attribute the_list on c1, and if not found there, then look it up in the superclass. The append does not change the attribute, it just changes the value that the attribute points to.

Now if you were to write an example that superficially looks the same:

c1.the_list+=[42]

It would work identical to

original=getattr(c1,'the_list')new_value=original+[42]setattr(c1,'the_list',new_value)

And do a completely different thing: first of all the original + [ 42 ] would create a new list object. Then the attribute the_list would be created in c1, and set to point to this new list. That is, in case of instance.attribute, if the attribute is "read from", it can be looked up in the class (or superclass) if not set in the instance, but if it is written to, as in instance.attribute = something, it will always be set on the instance.

As for this:

classTest1(object):self.i=1

Such thing does not work in Python, because there is no self defined when the class body (that is all lines of code within the class) is executed - actually, the class is created only after all the code in the class body has been executed. The class body is just like any other piece of code, only the defs and variable assignments will create methods and attributes on the class instead of setting global variables.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值