[Python3]python中的类变量和构造函数分析

本文探讨Python中构造函数、成员变量与C++的差异,解析Python构造函数的灵活性,成员变量的声明方式,及为何Python不存在静态成员变量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文的目的,就是在python3中找到C++中的构造函数,普通成员变量,静态成员变量的对应方法,并总结易错点

我们从普通成员变量开始讨论,下面这段代码,暗藏着问题

>>> class T:
	classNum = 10
	def __init__(self):
		objectNum = 99
	def changeNum(self, anotherNum):
		self.objectNum = anotherNum
	def showNum(self):
		print("self.num = ", self.objectNum, sep ="", end="")

什么问题呢?里面的__init__函数中的变量objectNum看似是在对象示例化的时候就自动创建并初始化为99,对于一个熟悉C++的程序员,似乎再对不过,不就是我们在changeNum()和showNum()函数中显式地调用了this指针(python中为self),而在__init__函数中隐式地使用this指针(python中为self)

这篇文章就是要指出,如果一个C++程序员将C++中的 (*this) 和 python 中的self直接画上等号,那就大错特错

其实,我们只需要一小段测试代码就可以发现问题:

>>> t1 = T()
>>> t1.showNum()
Traceback (most recent call last):
  File "<pyshell#36>", line 1, in <module>
    t1.showNum()
  File "<pyshell#34>", line 8, in showNum
    print("self.num = ", self.objectNum, sep ="", end="")
AttributeError: 'T' object has no attribute 'objectNum'

报错了,提示实例化对象t1并没有objectNum这个普通成员变量,为什么呢?

问题就在于,在Python中,类的成员变量必须使用self.propertName进行声明,这样才能完成创建

在这个类T中,objectNum和self.objectNum就是两个完全不同的东西:

定义在__init__函数中的变量objectNum在这里是一个局部变量,不是类变量

 

例如我们可以再写一段代码,调用changeNum()方法,从而生成这个普通成员变量objectNum:

>>> t1.changeNum(100)
>>> t1.showNum()
self.num = 100

由于在changeNum()方法中,有self.objectNum = anotherNum的赋值,而__init__中,没有创建类普通成员变量self.objectNum

而是创建了一个临时变量objectNum,所以在这里,虽然changeNum()没有被自动调用(因为不是__init__()函数),但是其实充当了创建类成员变量和初始化的作用,某种意义上来说,这里的changeNum()方法倒有点C++中的"构造函数"的意味,唯一不同的就是python并不会在创建新的实例化对象的时候自动调用它

通过上面的简单讨论,我们暂时得出了三条结论:

1.python中的"构造函数"非常的自由,如果不考虑自动调用,任何类方法都可以去创建类成员变量:

class ExampleClass:
	def createObjectProperty(self, value):
		self.newObjectProperty = value

如上面的代码,这里声明一个类方法,传入参数self 和 value,调用这个方法,就可以生成一个普通成员变量newObjectProperty,并对其赋初值value

2.如果想要找到真正意义上和C++中的构造函数对应的构造函数,那么只需要在__init__(self)中声明self.objectProperty即可

3.python中的self不能隐式调用,如果你不想生成一个临时变量而是创建一个类成员变量,那么就应该使用self.variableName

>>> class T:
	classNum = 10
	def __init__(self):
		self.objectNum = 99
	def changeNum(self, anotherNum):
		self.objectNum = anotherNum
	def showNum(self):
		print("self.num = ", self.objectNum, sep ="", end="")

		
>>> t2 = T()
>>> t2.showNum()
self.num = 99

上面基本解决了普通成员变量和构造函数的问题,下面来讨论一下C++中静态成员变量在python中的对应:

>>> class T:
	classNum = 10
	def __init__(self):
		self.objectNum = 99
	def changeNum(self, anotherNum):
		self.objectNum = anotherNum
	def showNum(self):
		print("self.num = ", self.objectNum, sep ="", end="")

		
>>> T.classNum
10

在声明类T的时候,我们在所有的方法之外(但是仍在类的作用域中声明了一个变量classNum)

从命名的角度来看,我们希望这是一个类变量,我们不希望这次又是一个成员变量,测试发现它确实可以由类名直接访问

再试一下能否修改:

>>> T.classNum = 100
>>> T.classNum
100

发现可以修改,似乎已经具备了C++中static修饰的静态成员变量(类变量)的一半特征了

下面我们验证一下其是否能被所有实例化对象访问和修改,并检验是否具有类C++中类变量的全局特征(牵一发而动全身)

>>> t3 = T()
>>> t3.classNum
100
>>> t4 = T()
>>> t4.classNum
100
>>> T.classNum = 1000
>>> t3.classNum
1000
>>> t4.classNum
1000
>>> t3.classNum = 10000
>>> t4.classNum
1000
>>> t3.classNum
10000
>>> T.classNum
1000

从上面的数据,暂时可以看出:

使用类名.classNum修改其值会导致实例化对象的值全部改变,使用实例化对象名.classNum修改值,仅仅改变自己,管不了别的实例化对象中的classNum的值,也修改不了类名.classNum的值

但是这个推断正确吗?

我们检查一下内存,看一下其存储情况,是否和C++中一样静态成员变量应该指向同一内存,如果相同,那么就是和C++中一样,如果不同,那么python中就没有所谓的"静态成员变量"

>>> T.classNum is t3.classNum
False
>>> T.classNum is t4.classNum
True
>>> t3.classNum is t4.classNum
False
>>> T.classNum
1000
>>> t3.classNum
10000
>>> t4.classNum
1000
>>> T.classNum = 99999
>>> T.classNum
99999
>>> t3.classNum
10000
>>> t4.classNum
99999

出人意料的是,T.classNum和实例化对象t4.classNum中的内存是同一处,但是和实例化对象t3不是同一处

此时再次修改T.classNum,t4.classNum的值改变,t3.classNum的值不变,看来classNum的命名只是我们的美好愿望....

所以我们可以得出本文的最后第四条也是最后一条结论:

4.python3中没有静态成员变量

 

小结一下:

1.python中的"构造函数"非常的自由,如果不考虑自动调用,任何类方法都可以去创建类成员变量

2.如果想要找到真正意义上和C++中的构造函数对应的构造函数,那么只需要在__init__(self)中声明self.objectProperty即可

3.python中的self不能隐式调用,如果你不想生成一个临时变量而是创建一个类成员变量,那么就应该使用self.variableName

4.python3中没有静态成员变量

 

以上所有结论均由测试结果证明

测试版本号:Python3.6.0 部分语法在python2.x中不支持,如需动手实验,请在python3.x环境中进行

欢迎转载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值