类变量:可在类的所有实例之间共享的变量
实例类对象:类的实例是调用类对象来创建的。如: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.开头的变量!

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

python类变量与构造函数的使用的更多相关文章

  1. python 类变量 在多线程下的共享与释放问题

    最近被多线程给坑了下,没意识到类变量在多线程下是共享的,还有一个就是没意识到 内存释放问题,导致越累越大 1.python 类变量 在多线程情况 下的 是共享的 2.python 类变量 在多线程情况 ...

  2. Python 类变量和成员变量

    Python 类变量和成员变量 类与对象的方法 我们已经讨论了类与对象的功能部分,现在我们来看一下它的数据部分.事实上,它们只是与类和对象的名称空间 绑定 的普通变量,即这些名称只在这些类与对象的前提 ...

  3. Python中的构造函数

    Python中的构造函数是__init__函数.在Python中,子类如果定义了构造函数,而没有调用父类的,那么Python不会自动调用,也就是说父类的构造函数不会执行. 比如有test.py的mod ...

  4. python 类变量 在多线程下的共享与释放问题-乾颐堂

    最近被多线程给坑了下,没意识到类变量在多线程下是共享的,还有一个就是没意识到 内存释放问题,导致越累越大 1.python 类变量 在多线程情况 下的 是共享的 2.python 类变量 在多线程情况 ...

  5. 第7.13节 案例详解:Python类变量

    第7.13节 案例详解:Python类变量 上节介绍了类变量的定义和使用方法,并举例进行了说明.本节将通过一个更完整的例子来说明. 一.    定义函数dirp def dirp(iter): ret ...

  6. 第7.12节 可共享的Python类变量

    第7.12节 可共享的Python类变量 一.    引言 在上节已经引入介绍了类变量和实例变量,类体中定义的变量为类变量,默认属于类本身,实例变量是实例方法中定义的self对象的变量,对于每个实例都 ...

  7. 关于python类变量和实例变量

    今天在看python的类和实例的时候,突然发现了一个以前遗漏的点,也就是类变量和实例变量.首先需要理解一下类变量和实例变量的概念. 类全局变量:在类中定义,对类和由类生成的实例生效,如果通过方法对类变 ...

  8. python中的构造函数和析构函数

    python中的特殊方法,其中两个,构造函数和析构函数的作用: 比说“__init__”这个构造函数,具有初始化的作用,也就是当该类被实例化的时候就会执行该函数.那么我们就可以把要先初始化的属性放到这 ...

  9. Python类变量,实例变量,类方法,实例方法,静态方法的分析

    Python作为动态语言,跟静态语言如c/c++有很大区别,其中的一个重要的特性就是Python的变量无需声明直接可用.同样,类的成员变量无需声明,直接可用.目的是为了动态语言跟灵活,在思路想到的时候 ...

随机推荐

  1. 搭建solr8

    这里记录linux上的安装过程 一.下载安装包 https://lucene.apache.org/solr/downloads.html 二.解压安装 这里我放倒了/usr/local/solr目录 ...

  2. python_8_集合

    1.集合:可变集合set,不可变集合frozenset,集合是无序不重复的 set('hello') set9[1,2,3,4]) set((1,2,3)) 2.添加元素 > add:将元素整体 ...

  3. C# 接口练习

    #define debug using System; using System.Collections; namespace ConsoleApp1 { interface IAnimal { in ...

  4. PAT甲级——1025 PAT Ranking

    1025 PAT Ranking Programming Ability Test (PAT) is organized by the College of Computer Science and ...

  5. QuickSort(快速排序)原理及C++代码实现

    快速排序可以说是最重要的排序,其中延伸的思想和技巧非常值得我们学习. 快速排序也使用了分治的思想,原理如下: 分解:数组A[p..r]被划分为两个(可能为空)子数组A[p..q-1]和A[q+1..r ...

  6. Fastjson主要接口和类库说明

    2.主要的使用入口 Fastjson API入口类是com.alibaba.fastjson.JSON,常用的序列化操作都可以在JSON类上的静态方法直接完成. public static final ...

  7. Linux下安装mysql(yun方式)

    1.进入下载好的mysql版本 cd /usr/local/mysql 2.解压安装包 tar -xzvf mysql-5.7.11.tar.gz 3.改名 直接改或者 mv  文件名 要改的文件名m ...

  8. Qt QLabel show 显示图像、填充、缩放

    主要成员函数: 1.void setText(QString); //设置label框内的文本. 2.void hide(); //隐藏label框. 3.void setBuddy(QWidget* ...

  9. pytorch中的view函数和max函数

    一.view函数 代码: a=torch.randn(,,,) b = a.view(,-) print(b.size()) 输出: torch.Size([, ]) 解释: 其中参数-1表示剩下的值 ...

  10. MS15-020 文件共享漏洞利用

    Metasploit MS15-020漏洞利用 环境: 共享机/受害者:windows xp IP:192.168.222.1 攻击机:kali linux IP:192.168.10.1 msfco ...