python的类和对象(类的静态字段)
转自:http://www.cnblogs.com/Eva-J/p/5044411.html
什么是静态字段
在开始之前,先上图,解释一下什么是类的静态字段(我有的时候会叫它类的静态变量,总之说的都是它。后面大多数情况可能会简称为类变量。):

我们看上面的例子,这里的money就是静态字段,首先看它的位置,是在father类中,而不是在__init__中。那么一个小小的静态字段,我为什么要特意写一篇番外给它呢?耐着性子看下去,你就会发现一个小小的类变量,却折射出了整个类的世界。
首先我们先来解释一下什么叫做静态字段:

我们看上面的例子,左中右三张图,左边是纯净的代码,中间是我给代码加上的内存加载过程,右边是执行结果。我们在这里先看中间的图,来看这个文件加载的过程。
1.将类存入了内存 2.将money变量放入了内存 3.将__init__方法的地址放入了内存
接下来我们执行了一个__dict__方法,我们看右边图中现实的执行结果,发现这个时候内存中已经存入了money这个变量,它随着这个程序 的执行产生,随着程序的结束而消失,这样和程序‘共存亡’的字段,我们就叫它静态字段。它就像是一个全局变量,不属于任何一个对象,我们可以直接使用类来 调用,也可以在对象使用方法的时候使用它。它是对象共享的变量,存在类的内存里。
静态字段的调用方法
刚刚我们知道了什么是静态字段,现在我们就来看看静态字段是怎么使用的?

上面给出了两种使用方式,类调用和对象调用,哎?看起来好像可以哎!我们再来修改一下类变量瞧瞧:

我们看,当我们使用 类名.静态字段名 修改类变量之后,使用类或者对象去调用这个静态字段,发现它们都产生了变化。好像一切都在我们的预料之中哎,这样的话对象和类都可以使用类变量的样子!如果你们真的信了那就太天真了。。。看看下面这个例子:

看上面的图,我是接着上面的例子写的,黄框框里是我加上的内容,我们结果中最后打印出来的内容,哎?我们看到了什么?好像对象调用的类变量只是 针对各自的对象发生了改变,并没有改变类中money变量的值,说好的全局变量呢?这个现象是怎么发生的呢?我们不防来推理一下:

看上面两张图,左边是正常的逻辑,当我们类的内存中有一个静态字段的时候,我们使用类去调用这个字段,自然找到的是静态字段,当我们使用对象去 调用的时候,这个对象指针先在自己的内存里找了找,发现没找到,于是就用对象中维护的类指针到类的内存中去找,果然找到了money,于是欢欢喜喜的打印 了出来,我们也如愿以偿的看到了想要的结果。当我们使用 类 去调用这个静态字段进行修改的时候,我们修改的是 类 的内存中维护的money字段,所以并没有影响上述过程。
再看右边这张图,当我们使用对象去调用并改变一个类的静态字段的时候,它们在自己的内存中并没有money字段,所以还是通过类指针到类内存中 去找,但是当它们找到之后,就会在自己的内存空间开辟一块空间来存储对这个静态字段修改后的结果。所以,这个时候类中的静态字段就不会被改变,而两个对象 中的money字段也就不会互相影响了。

这个时候我们在刚刚的基础上再加上一段代码,来看执行的结果,我们发现这个时候再使用类变量对类的静态变量进行修改,分别看看类和对象中这个变 量的变化,我们发现对象中的变量没有按照我们期待的那样发生改变,这也验证了我们的猜想,因为这个时候对象的内存中已经有了money变量,它们就不愿意 舍近求远的到类内存中去取变量来给我们显示了。

#!/usr/bin/env python
#-*-coding:utf-8-*-
__author__ = 'Eva_J'
class father(object): #静态字段
money = 10000
def __init__(self,name): #普通字段
self.name = name #类的实例化,分别实例化出了两个对象father_obj1,father_obj2
father_obj1 = father('obj1')
father_obj2 = father('obj2') #类调用
print 'father.money:',father.money
#对象调用
print 'father_obj1.money:',father_obj1.money
print 'father_obj2.money:',father_obj2.money #使用类调用修改
father.money = father.money + 1000
print 'father.money:',father.money
print 'father_obj1.money:',father_obj1.money
print 'father_obj2.money:',father_obj2.money #使用对象调用修改
father_obj1.money = father_obj1.money + 1
father_obj2.money = father_obj2.money + 2
print 'father.money:',father.money
print 'father_obj1.money:',father_obj1.money
print 'father_obj2.money:',father_obj2.money father.money = father.money + 66
print 'father.money:',father.money
print 'father_obj1.money:',father_obj1.money
print 'father_obj2.money:',father_obj2.money demo Code

但是,我们变量类型换乘字典试试看,结果又不一样了,代码在下面,自己粘回去执行吧,这里就不给你们贴花花绿绿的图了:

#!/usr/bin/env python
#-*-coding:utf-8-*-
__author__ = 'Eva_J'
class father(object): #静态字段
money = {'money':10000}
def __init__(self,name): #普通字段
self.name = name #类的实例化,分别实例化出了两个对象father_obj1,father_obj2
father_obj1 = father('obj1')
father_obj2 = father('obj2')
#类调用
print 'father.money:',father.money['money']
#对象调用
print 'father_obj1.money:',father_obj1.money['money']
print 'father_obj2.money:',father_obj2.money['money'] #使用类调用修改
father.money['money'] = father.money['money'] + 1000
print 'father.money:',father.money['money']
print 'father_obj1.money:',father_obj1.money['money']
print 'father_obj2.money:',father_obj2.money['money'] #使用对象调用修改
father_obj1.money['money'] = father_obj1.money['money'] + 1
father_obj2.money['money'] = father_obj2.money['money'] + 2
print 'father.money:',father.money['money']
print 'father_obj1.money:',father_obj1.money['money']
print 'father_obj2.money:',father_obj2.money['money'] father.money['money'] = father.money['money'] + 66
print 'father.money:',father.money['money']
print 'father_obj1.money:',father_obj1.money['money']
print 'father_obj2.money:',father_obj2.money['money'] demo Code

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAVYAAADrCAIAAAC97inLAAAI4ElEQVR4nO3dXXqiShQFUIfFhK7DYTTXefTzdTDeh0TDT4EYbDlVZ62nNC0VO19qUyDsPv358+cGZHUSAZCZCIDURACkJgIgteUIuJxP386X5+N8vXrLK+O79t3wH3Ltu9PpdDp1/XXXFohoKQIu5+e/vJfzaM5P/lipaZb95MG1/6e//noLxLQSAc/m87Xv6ouALW9y+JrhiuBy7vr/frVFBhBWMQJ+zgEex8P7uvYxOR6vGfyun87nc3E5/LXhfoD93licipfzqeu62RlIaZzzeTxI4TWnrr/ev9weT8MImH7976+2hE9G8tq4Cnj8ceWX+3L+nmeP7de+u0/I71S4nJ+cHn+dgHyNMBvnMd7W73W+DP9mKxFAIptPBB7LgLUImMTEfDXxdD4MJ39xwJUvCiuX4SibOREgkXesAi6XhWk5ubQ+H3bp+25ZBTz9XrcNi46V9/DtZ9z7XP7dFohp67WA0bafX+rL/Xx8eGlgcFH9sXbo+v8Klw9uC1kziYDyef7K93rMuVkwbMmgyZv0oSAta/vWIIdgeKLVCLicHYJhg1YjANhEBEBqIgBSEwGQmgiA1EQApCYCIDURAKmJAEgtfnHYysiTG/6LTwqFopKMcKooDttY9fOXMuhdVJIRURXFYRtHPracQyUZVYpWHDbfazTyYJ/5YX99Eqokg4JoxWGDveY1YdMKsJfORFSSQUG04rClcYq7vxoBKslgKlpx2G2tJmzvKkAlGUwdXhxWMrsW0Hddac9JHm1ZpKgkg5Gabw2afiTxSQ7BNOLYCBguLbYtEEZ7HTILVZLRlJpXAcBuIgBSEwGQmgiA1EQApCYCIDURAKmJAEhNBEBqrRSH/TzIGPkBWsVhhNNGcdigQ+vxvH84isOIqI3isAhFGorDqFJLxWHfmxfmheIwKGipOGy9RlxxGBQ0VBz25PKF4jAoaKQ4bHhd4tr3yx8fKA6DkTaKw8bVI9PJPHyx4jAYqfnWIMVhsJvisFcpDqMpNa8CgN1EAKQmAiA1EQCpiQBITQRAaiIAUhMBkJoIgNTiF4d93vy5oLcUfkFEVRSHfdI8y95T+AUxVVEc9kav1nvNt3iqn6ZEKw6LVu8136Lbh6ZEKw6LVu813yICaEq04rBo9V7zLU4EaEq04rBw9V7zLeq9aMnhxWHx673eVfgFEbV9a5BDMDzRagSo94JNWo0AYBMRAKmJAEhNBEBqIgBSEwGQmgiA1EQApCYCILX4xWErI09u+C8+KRSKSjLCqaI4bGPVz1/KoHdRSUZEVRSHbRz52HIOlWRUKVpx2Hyv0ciDfYoH1ZVJqJIMCqIVhw32mteETSvAXjoTUUkGBdGKw5bGKe7+agSoJIOpaMVht7WasL2rAJVkMHV4cVjJ7FpA33WlPSd5tGWRopIMRmq+NWj6kcQnOQTTiGMjYLi02LZAGO11yCxUSUZTal4FALuJAEhNBEBqIgBSEwGQmgiA1EQApCYCIDURAKm1Uhz28yBj5AdoFYcRThvFYYMOrcfz/uEoDiOiNorDIhRpKA6jSi0Vh31vXpgXisOgoKXisPUaccVhUNBQcdiTyxeKw6CgkeKw4XWJa98vf3ygOAxG2igOG1ePTCfz8MWKw2Ck5luDFIfBborDXqU4jKbUvAoAdhMBkJoIgNREAKQmAiA1EQCpiQBITQRAaiIAUotfHPZ5b6j3GvSYNfJDoVVVFId90lvqvQZPEBz5IAM8V0Vx2Bt9ot5rlJxrLSZwvGjFYS3Ue42eBfY8EbFFKw5rod7rtRoBOFS04rAW6r2ui/tCONGKw9qo9xoEwZbrqnCcw4vD2qz3quM/N4LWbw1S7wVPtBoB6r1gk1YjANhEBEBqIgBSEwGQmgiA1EQApCYCIDURAKmJAEgtfnHYysiTG/7jt3OoJCOcKorDNlb9BJ8UKsmIqIrisI0jH/tkvkoyqhStOGy+12jkwT7Fg+rKnFBJBgXRisNuCwUhp/NlXgH20pmISjIoiFYctjROcfdXI0AlGUxFKw67rdWE7V0FqCSDqcOLw0pm1wL6rivtOTs9fr5IUUkGIzXfGnTkp2IqyWjEsREwXFpsP7I99jpkFqokoyk1rwKA3UQApCYCIDURAKmJAEhNBEBqIgBSEwGQmgiA1FopDqvj1nnFYYTTRnHYvWfrNnjePxzFYUTURnHYarXGhygOo0otFYd9b15YvSgOg4KWisPWD4yKw6CgoeKwJ5cvFIdBQSPFYcPrEte+X/74QHEYjLRRHDauHplO5uGLFYfBSM23BikOg90Uh71KcRhNqXkVAOwmAiA1EQCpiQBITQRAaiIAUhMBkJoIgNREAKQWvzjs835R7zWrDig8WAkRVVEc9kl76r2GDxfed2jjp0K7qigOe6O/VO81icsIRWawSbTisFrrvfrRz+cnHa9951yAyKIVh1Va73X/Nw3exf1hxt4qgMiiFYfVX+81/7l5sJjAohWHVVnvNSowG79DCUBwhxeHtVXvNf3RvHQNAg7Q9q1B6r3giVYjQL0XbNJqBACbiABITQRAaiIAUhMBkJoIgNREAKQmAiA1EQCpxS8OWxl5csN/8UmhUFSSEU4VxWEbq36CzwqVZERURXHYxpGPnRMqyahStOKw+V6jkQf7FA+qK1NCJRkURCsOuy0UhBT7N146E1FJBgXRisOWxinu/moEqCSDqWjFYbe1mrC9q4B5BKgkI7vDi8NKZtcC+q4r7TnJoy2LFJVkMFLzrUHTjyQ+SSUZjTg2AoZLi+1Htsdeh8xClWQ0peZVALCbCIDURACkJgIgNREAqYkASE0EQGoiAFITAZBaK8VhPw8yRr51XnEY4bRRHHbv2boNnvcPR3EYEbVRHBahTktxGFVqqTjse/PC6kVxGBS0VBy2XiOuOAwKGioOe3L5QnEYFDRSHDa8LnHt++WPDxSHwUgbxWHj6pHpZB6+WHEYjNR8a5DiMNhNcdirFIfRlJpXAcBuIgBSEwGQmgiA1EQApCYCIDURAKmJAEhNBEBqIgBSEwGQ2v9YE8d/u4+R3wAAAABJRU5ErkJggg==" alt="" />
偷懒的同学看这里→_→ :我们只需要记住,在使用类的静态变量的时候,必须要用类名来调用和修改。它才会永远被类和对象共享。
从类的继承这个角度来看看静态字段
刚刚我们已经知道了对象和类中静态字段的存储及调用过程,下面我们就从类的继承这个角度来看看静态字段:

1 #!/usr/bin/env python
2 #-*-coding:utf-8-*-
3 __author__ = 'Eva_J'
4 class father(object):
5
6 #静态字段
7 money = 10000
8 def __init__(self,name):
9
10 #普通字段
11 self.name = name
12
13 class Son1(father):
14 pass
15
16 class Son2(father):
17 pass
18
19 class GrandSon(Son1,Son2):
20 pass
21
22 print 'father.money : ',father.money
23 print 'Son1.money : ',Son1.money
24 print 'Son2.money : ',Son2.money
25 print 'GrandSon.money : ',GrandSon.money
26 print '*'*25
27 father.money += 1000
28 print 'father.money : ',father.money
29 print 'Son1.money : ',Son1.money
30 print 'Son2.money : ',Son2.money
31 print 'GrandSon.money : ',GrandSon.money
32 print '*'*25
33 Son1.money += 100
34 Son2.money += 200
35 print 'father.money : ',father.money
36 print 'Son1.money : ',Son1.money
37 print 'Son2.money : ',Son2.money
38 print 'GrandSon.money : ',GrandSon.money
39 print '*'*25
40 GrandSon.money += 1
41 print 'father.money : ',father.money
42 print 'Son1.money : ',Son1.money
43 print 'Son2.money : ',Son2.money
44 print 'GrandSon.money : ',GrandSon.money
45 print '*'*25
46 father.money += 2000
47 print 'father.money : ',father.money
48 print 'Son1.money : ',Son1.money
49 print 'Son2.money : ',Son2.money
50 print 'GrandSon.money : ',GrandSon.money
51
52 demoCode

上面这段代码的执行结果是这样的:

原理在下面,当我们使用创建类的时候,每个基类和派生类都会产生自己的内存,一开始派生类中没有money变量,所以在调用的时候它们通过类中 维护的指针都顺利地找到了父类中的money变量,返回给了我们,但是当我们使用 派生类名.静态字段名 对派生类中的静态字段进行修改的时候,它们就默默地把修改的结果存在了自己的内存空间内。所以在之后的调用中就不千里迢迢的去父类中找这个变量了。其实和 上面的道理是一样一样哒!

偷懒的同学看这里→_→ :我们只需要记住,在使用类的静态变量的时候,如果我们希望基类和各派生类的静态字段被共享,必须要用基类名来调用和修改。
到这里关于类的静态字段的内容就全部讲完了,简简单单的一个静态字段,竟然囊括了这么多知识点,是不是值得我们花一点点时间来搞清楚呢?
python的类和对象(类的静态字段)的更多相关文章
- python的类和对象——类的静态字段番外篇
什么是静态字段 在开始之前,先上图,解释一下什么是类的静态字段(我有的时候会叫它类的静态变量,总之说的都是它.后面大多数情况可能会简称为类变量.): 我们看上面的例子,这里的money就是静态字段,首 ...
- php笔记(二)PHP类和对象之Static静态关键字
PHP类和对象之Static静态关键字 静态属性与方法可以在不实例化类的情况下调用,直接使用类名::方法名的方式进行调用.静态属性不允许对象使用->操作符调用. class Car { pr ...
- python的类和对象——类成员番外篇
学完了面向对象的三大特性,已经get了所有屌丝技能的我们也当一回文艺小青年,来看看类的成员和成员修饰符. 今天‘三’这个数字好亲和~~~类成员可以分为三类:字段.方法和属性 一.字段 首先我们来看看字 ...
- 类实例化对象可以访问静态(static)方法,但是不能访问静态属性。
类-> 访问->静态方法(类的方法)->可以 类 ->访问->普通方法(对象的方法)->不可以(虽然方法里不用$this关键字时,可以!但不支持这种写法) 类-&g ...
- Java自学-类和对象 类属性
Java的类属性和对象属性 当一个属性被static修饰的时候,就叫做类属性,又叫做静态属性 当一个属性被声明成类属性,那么所有的对象,都共享一个值 与对象属性对比: 不同对象的 对象属性 的值都可能 ...
- java学习-初级入门-面向对象③-类与对象-类与对象的定义和使用1
今天学习类与对象.先大致解释一下类与对象的含义. 对象:object 有物体这一概念,一切皆对象(物体),对象由静态的属性和动态的行为组成. 比如说水杯: 水杯的静态属性:材质,容量,质量,颜色 动态 ...
- Java序列化机制中的类版本问题 serialVersionUID的静态字段 含义
Java序列化机制中的类版本问题 分类: [Java 基础]2014-10-31 21:13 480人阅读 评论(0) 收藏 举报 目录(?)[+] 原文地址:http://yanwu ...
- java基础:详解类和对象,类和对象的应用,封装思想,构造方法详解,附练习案列
1. 类和对象 面向对象和面向过程的思想对比 : 面向过程 :是一种以过程为中心的编程思想,实现功能的每一步,都是自己实现的 面向对象 :是一种以对象为中心的编程思想,通过指挥对象实现具体的功能 1. ...
- java学习-初级入门-面向对象⑤-类与对象-类与对象的定义和使用3
这次我们要做一个日期类Date类 主要目的是 1. 熟悉-->构造不同参数的函数 2.善于利用已有的函数!! 题目要求: Date类要求 可设定年月日 可转换为字符串,并可指定分隔符, ...
- java学习-初级入门-面向对象④-类与对象-类与对象的定义和使用2
我们继续学习类与对象,上一篇我们定义了 坐标类(Point), 这次我们在Point的基础上,创建一个圆类(Circle). 案例:创建一个圆类 题目要求: 计算圆的周长和面积:求判断两个圆的位置关 ...
随机推荐
- 最长不下降子序列nlogn
b[i]表示长度为i的最长不下降子序列的最小末尾元素的值显然它是单调递增的,满足二分性质,然后就可以愉快地二分啦. #include<iostream> #include<cstdi ...
- 基于Ardalis.GuardClauses守卫组件的拓展
在我们写程序的时候,经常会需要判断数据的是空值还是null值,基本上十个方法函数,八个要做这样的判断,因此我们很有必要拓展出来一个类来做监控,在这里我们使用一个简单地,可拓展的第三方组件:Ardali ...
- XamarinSQLite教程在Xamarin.Android项目中定位数据库文件
XamarinSQLite教程在Xamarin.Android项目中定位数据库文件 实际开发中,经常需要验证数据库操作的正确性.这个时候,需要打开数据库文件,进行确认.下面是如何找到MyDocumen ...
- Yolov3实战 基于darknet window版
特此声明:训练过程预先认为你对yolov3神经网络有一定了解的基础上进行. 目录 一.先备齐下面的工具(预先善其事,必先利其器) 二.接下里使用我们的工具编译我们的环境 三. 训练自己的数据集 1. ...
- 使用C#的is、as操作符来转型
is检查对象是否兼容于指定类型,返回Boolean值true或false.使用is永远不会抛出异常. 例:Object o=new Object(); bool b1=(o is Object);// ...
- 2018-6-25-随笔-MVC
向IIS中注册.net框架版本:安装的IIS因为是先安装了VS所以它里面的应用程序池的.net框架还是系统自带的框架,Win7是2.0,需要将VS的.net框架版本注册 注册方法:在开始菜单找到VS2 ...
- 在Qt中调用Mupdf库进行pdf显示
2018.5.10 更新内存对齐说明 感谢知乎网友@孤独子狮 指出QImage处需要考虑内存对齐的问题.因为本人缺乏跨平台.图形库开发经验,所以在调试成功后就没有深入探究. 主要修改了QImage的构 ...
- [python]Flask-migrate简单入门
Flask-Migrate是用于处理SQLAlchemy 数据库迁移的扩展工具.当Model出现变更的时候,通过migrate去管理数据库变更. Migrate主要有3个动作,init.migrate ...
- 第一章 C++ primer Plus
第一章 1.4程序创建的技巧 大体如下: 1.使用文本编辑器编写程序,并将其保存到文件中,这个文件就是程序的源代码. 2.编译源代码.这意味着运行一个程序,将源代码翻译为主机使用的内部语言——机器语言 ...
- Mybatis批量插入返回自增主键(转)
我们都知道Mybatis在插入单条数据的时候有两种方式返回自增主键: 1.对于支持生成自增主键的数据库:useGenerateKeys和keyProperty. 2.不支持生成自增主键的数据库:< ...