python的类和对象——番外篇(类的静态字段)
什么是静态字段
在开始之前,先上图,解释一下什么是类的静态字段(我有的时候会叫它类的静态变量,总之说的都是它。后面大多数情况可能会简称为类变量。):

我们看上面的例子,这里的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
为什么?这就和不同数据类型维护的指针有关系了。在这里不详细的赘述。
偷懒的同学看这里→_→ :我们只需要记住,在使用类的静态变量的时候,必须要用类名来调用和修改。它才会永远被类和对象共享。
从类的继承这个角度来看看静态字段
刚刚我们已经知道了对象和类中静态字段的存储及调用过程,下面我们就从类的继承这个角度来看看静态字段:
#!/usr/bin/env python
#-*-coding:utf-8-*-
__author__ = 'Eva_J'
class father(object): #静态字段
money = 10000
def __init__(self,name): #普通字段
self.name = name class Son1(father):
pass class Son2(father):
pass class GrandSon(Son1,Son2):
pass print 'father.money : ',father.money
print 'Son1.money : ',Son1.money
print 'Son2.money : ',Son2.money
print 'GrandSon.money : ',GrandSon.money
print '*'*25
father.money += 1000
print 'father.money : ',father.money
print 'Son1.money : ',Son1.money
print 'Son2.money : ',Son2.money
print 'GrandSon.money : ',GrandSon.money
print '*'*25
Son1.money += 100
Son2.money += 200
print 'father.money : ',father.money
print 'Son1.money : ',Son1.money
print 'Son2.money : ',Son2.money
print 'GrandSon.money : ',GrandSon.money
print '*'*25
GrandSon.money += 1
print 'father.money : ',father.money
print 'Son1.money : ',Son1.money
print 'Son2.money : ',Son2.money
print 'GrandSon.money : ',GrandSon.money
print '*'*25
father.money += 2000
print 'father.money : ',father.money
print 'Son1.money : ',Son1.money
print 'Son2.money : ',Son2.money
print 'GrandSon.money : ',GrandSon.money
demoCode
上面这段代码的执行结果是这样的:

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

偷懒的同学看这里→_→ :我们只需要记住,在使用类的静态变量的时候,如果我们希望基类和各派生类的静态字段被共享,必须要用基类名来调用和修改。
到这里关于类的静态字段的内容就全部讲完了,简简单单的一个静态字段,竟然囊括了这么多知识点,是不是值得我们花一点点时间来搞清楚呢?
python的类和对象——番外篇(类的静态字段)的更多相关文章
- python的类和对象——类的静态字段番外篇
什么是静态字段 在开始之前,先上图,解释一下什么是类的静态字段(我有的时候会叫它类的静态变量,总之说的都是它.后面大多数情况可能会简称为类变量.): 我们看上面的例子,这里的money就是静态字段,首 ...
- 给深度学习入门者的Python快速教程 - 番外篇之Python-OpenCV
这次博客园的排版彻底残了..高清版请移步: https://zhuanlan.zhihu.com/p/24425116 本篇是前面两篇教程: 给深度学习入门者的Python快速教程 - 基础篇 给深度 ...
- openresty 学习笔记番外篇:python的一些扩展库
openresty 学习笔记番外篇:python的一些扩展库 要写一个可以使用的python程序还需要比如日志输出,读取配置文件,作为守护进程运行等 读取配置文件 使用自带的ConfigParser模 ...
- python自动化测试应用-番外篇--接口测试1
篇1 book-python-auto-test-番外篇--接口测试1 --lamecho辣么丑 1.1概要 大家好! 我是lamecho(辣么丑),至今<安卓a ...
- python自动化测试应用-番外篇--接口测试2
篇2 book-python-auto-test-番外篇--接口测试2 --lamecho辣么丑 大家好! 我是lamecho(辣么丑),今天将继续上一篇python接 ...
- python之爬虫--番外篇(一)进程,线程的初步了解
整理这番外篇的原因是希望能够让爬虫的朋友更加理解这块内容,因为爬虫爬取数据可能很简单,但是如何高效持久的爬,利用进程,线程,以及异步IO,其实很多人和我一样,故整理此系列番外篇 一.进程 程序并不能单 ...
- #3使用html+css+js制作网页 番外篇 使用python flask 框架 (II)
#3使用html+css+js制作网页 番外篇 使用python flask 框架 II第二部 0. 本系列教程 1. 登录功能准备 a.python中操控mysql b. 安装数据库 c.安装mys ...
- #3使用html+css+js制作网页 番外篇 使用python flask 框架 (I)
#3使用html+css+js制作网页 番外篇 使用python flask 框架(I 第一部) 0. 本系列教程 1. 准备 a.python b. flask c. flask 环境安装 d. f ...
- openresty 学习笔记番外篇:python访问RabbitMQ消息队列
openresty 学习笔记番外篇:python访问RabbitMQ消息队列 python使用pika扩展库操作RabbitMQ的流程梳理. 客户端连接到消息队列服务器,打开一个channel. 客户 ...
随机推荐
- WEB语言转义总结
后台字符串嵌入前台语言输出 web语言分为后台和前台,如果后台语言嵌入方式将字符串输出到前台语言中,需要按照前台语言的要求进行转义. 因为前台各个语言都有自身的保留字符, 用于规定自身的语法格式, ...
- 使用ScheduledExecutorService实现Timer
大家都说Timer不太好用,经常会遇到:如果前边的一个任务比较慢,超出了period,此时timer的下一次轮询也会延迟. 同事说ScheduleExecutorService可以避免该问题,我写个例 ...
- Eclipse in Ubuntu16.04LTS Final Beta
#2016.03.30 在虚拟机Ubuntu16.04LTS上,用Eclipse编写运行Java,就目前而言,实在不是明智之举.卡顿极其厉害,还是在物理机上运行吧.那么继续Ubuntu的探索历程. 用 ...
- windows系统调用 利用事件对象实现进程通信
#include "iostream" #include "windows.h" #include "cstring" using name ...
- Android--Retrofit+RxJava(二)
1,现在响应式编程也是越来越多在项目中使用了,刚好上篇我们简单了介绍了一下Retrofit,那么我们来开始试着两个一起用吧,不过不了解RxJava的同学可以先去看一看这个文章(挺好的):http:// ...
- maven nexus
部署nexus步骤: 1.下载解压安装包到指定目录 2.设置环境变量(当然还有JAVA,jdk) 3.在配置文件(G:\nexus\nexus-2.3.1-01-bundle\nexus-2.3.1- ...
- xcode8集成百度地图(framwork包) archive是bitcode问题
(1)问题描述:真机和模拟器测试都能编译安装,但是需要打包archive的时候 总是编译出错,眼看就要上线了,还出现这问题,纠结啊.... 打印出来的错误: ld: bitcode bundle co ...
- error: linker command failed with exit code 1 解决方法之一
出现这种错误的原因可能很多,以下是我遇到的一种情况: 向项目中添加了新文件,没有加入compile source 编译报错: ld: symbol(s) not found for architect ...
- (转)libcurl应用:如何把下载内容写入内存
libcurl应用:如何把下载内容写入内存 2008-01-13 00:32:52| 分类: 默认分类 |举报 |字号 订阅 libcurl的文档中有 getinmemory.c这个例子,把下载 ...
- python 注意事项
常见错误 #4: 不理解Python的作用域 Python是基于 LEGB 来进行作用于解析的, LEGB 是 Local, Enclosing, Global, Built-in 的缩写.看起来“ ...