python类变量与构造函数的使用

类变量:可在类的全部实例之间共享的变量
实例类对象:类的实例是调用类对象来建立的。如:par = Parent(),par就是类Parent的一个实例类对象。
实例变量(成员变量):同一个类对象能够建立多个实例类对象,类定义中有self标志的变量就是实例变量
 
一个例子,下面的代码有问题
class MyObject(object): x = 1
    def __init__(self): objectNum = 99
    def changeNum(self, anotherNum): self.objectNum = anotherNum def showNum(self): print("self.num = ", self.objectNum)
什么问题呢,看似构造函数__init__中的变量object在实例化对象的时候会自动建立并初始化为99,其实否则,这里用一个小的测试代码就能够发现问题。
obj = MyObject() obj.showNum() Traceback (most recent call last): File "class.py", line 24, in <module> obj.showNum() File "class.py", line 20, in showNum print("self.num = ", self.objectNum) AttributeError: 'MyObject' object has no attribute 'objectNum'
报错了,提示实例化对象MyObject并无objectNum这个普通成员变量,为何呢?
问题就在于,在Python中,类的成员变量必须使用self.propertName进行声明,这样才能完成建立,由于self的含义就是表明实例对象;
在这个类中,objectNum和self.objectNum就是两个彻底不一样的东西:
定义在__init__函数中的变量objectNum在这里是一个局部变量,不是类变量
 
接下来咱们能够再写一段代码,调用changNum()方法,来生成这个成员变量self.objectNum:
obj = MyObject() obj.changeNum(10) obj.showNum() >>> self.num =  10
能看到成功返回结果,
因为在changeNum()方法中,有self.objectNum = anotherNum的赋值,而__init__中,没有建立类普通成员变量self.objectNum, 而是建立了一个临时变量objectNum,因此在这里,虽然changeNum()没有被自动调用(由于不是__init__()函数),可是其实充当了建立类成员变量和初始化的做用, 可是python并不会在建立新的实例化对象的时候自动调用它。
 
因此经过实验获得3个结论:
1.python中的"构造函数"很是的自由,若是不考虑自动调用,任何类方法均可以去建立类成员变量:
class ExampleClass: def createObjectProperty(self, value): self.newObjectProperty = value
如上面的代码,这里声明一个类方法,传入参数self 和 value,调用这个方法,就能够生成一个普通成员变量newObjectProperty,并对其赋初值value
2.若是想要找到真正意义上的成员变量,那么只须要在__init__(self)中声明self.objectProperty便可
3.python中的self不能隐式调用,若是你不想生成一个临时变量而是建立一个类成员变量,那么就应该使用self.variableName
class MyObject(object): x = 1
    def __init__(self): self.objectNum = 99
    def changeNum(self, anotherNum): self.objectNum = anotherNum def showNum(self): print("self.num = ", self.objectNum)
obj = MyObject()
# obj.changeNum(10)
obj.showNum()
>>>self.num =  99
知道了成员变量的问题以后,再来讨论一下类变量
class MyObject(object): x = 1
    def __init__(self): self.objectNum = 99
    def changeNum(self, anotherNum): self.objectNum = anotherNum def showNum(self): print("self.num = ", self.objectNum) obj = MyObject() print(MyObject.x) >>> 1

 

在声明类T的时候,咱们在全部的方法以外(可是仍在类的做用域中声明了一个变量classNum),从命名的角度来看,咱们但愿这是一个类变量,但咱们不但愿此次又是一个成员变量,测试发现它确实能够由类名直接访问再试一下可否修改:
MyObject.x = 100
print(MyObject.x) >>> 100
发现能够修改
下面咱们验证一下其是否能被全部实例化对象访问和修改,而且是否具备全局性。
t1 = MyObject() print(t1.x) >>> 1 t2 = MyObject() print(t2.x) >>> 1 MyObject.x = 1000
print(t1.x) >>> 1000
print(t2.x) >>> 1000 t1.x = 2000
print(t2.x) >>>1000
print(t1.x) >>>2000
print(MyObject.x) >>>1000
 
从以上结果看出类名.类变量名修改其值会致使实例化对象的值所有被改变,可是用实例化对象名.类变量名修改其值,就仅仅改变本身,不会真的改变类变量的数值。
咱们来检查一下内存,看一段代码:
t2 = MyObject() t1 = MyObject() print(MyObject.x is t1.x) >>>True print(MyObject.x is t2.x) >>>True print(t2.x is t1.x) >>>True --------------------------------------- t2 = MyObject() t1 = MyObject() t2.x = 10
print(MyObject.x is t1.x) >>>True print(MyObject.x is t2.x) >>>False print(t2.x is t1.x) >>>False -------------------------------------- t2 = MyObject() t1 = MyObject() MyObject.x = 100 t2.x = 10
print(MyObject.x is t1.x) >>>True print(MyObject.x is t2.x) >>>False print(t2.x is t1.x) >>>False
看得出来在最开始的时候MyObject.x和实例化对象t1.x与t2.x内存是同一处的,但当直接修改了实例化对象t2.x的数值后t2.x内存的数值便与其余两个不一样,因此直接修改实例化对象的数值会指向新的内存空间,而且不受类变量改变而改变。
总结:
一个类=类变量(能够没有)+构造函数(必须有,没有的话默认调用)+成员函数(本身定义,能够没有)

构造函数中定义了类的成员变量,类的成员变量必定是在构造函数中以self.开头的变量!python

成员函数中能够调用成员变量和类变量!成员函数的形参在类的实例调用该函数时传递,成员函数的局部变量在该成员函数内部定义。调用成员函数和调用普通函数同样,只是成员函数由该函数对应的类调用,即须要写成xxxx.func()而不是直接使用func()!

函数

相关文章
相关标签/搜索