Python的类实例属性访问规则探讨


Posted in Python onJanuary 30, 2015

一般来说,在Python中,类实例属性的访问规则算是比较直观的。

但是,仍然存在一些不是很直观的地方,特别是对C++和Java程序员来说,更是如此。

在这里,我们需要明白以下几个地方:

1.Python是一门动态语言,任何实体都可以动态地添加或删除属性。
2.一个类定义了一个作用域。
3.类实例也引入了一个作用域,这与相应类定义的作用域不同。
4.在类实例中查找属性的时候,首先在实例自己的作用域中查找,如果没有找到,则再在类定义的作用域中查找。
5.在对类实例属性进行赋值的时候,实际上会在类实例定义的作用域中添加一个属性(如果还不存在的话),并不会影响到相应类中定义的同名属性。

下面看一个例子,加深对上述几点的理解:

class A:

      cls_i = 0

      cls_j = {}

      def __init__(self):

            self.instance_i = 0

            self.instance_j = {}

在这里,我们先定义类A的一个实例a,然后再看看类A的作用域和实例a的作用域中分别有什么:
>>> a = A()

>>> a.__dict__

{'instance_j': {}, 'instance_i': 0}

>>> A.__dict__

{'__init__': , '__module__': '__main__', 'cls_i': 0, 'cls_j': {}, '__doc__': None}

我们看到,a的作用域中有instance_i和instance_j,A的作用域中有cls_i和cls_j。

我们再来看看名字查找是如何发生的:

>>> a.cls_i

0

>>> a.instance_i

0

在查找cls_i的时候,实例a的作用域中是没有它的,却在A的作用域中找到了它;在查找instance_i的时候,直接可在a的作用域中找到它。

如果我们企图通过实例a来修改cls_i的值,那会怎样呢:

>>> a.cls_i = 1

>>> a.__dict__

{'instance_j': {}, 'cls_i': 1, 'instance_i': 0}

>>> A.__dict__

{'__init__': , '__module__': '__main__', 'cls_i': 0, 'cls_j': {}, '__doc__': None}

我们可以看到,a的作用域中多了一个cls_i属性,其值为1;同时,我们也注意到A作用域中的cls_i属性的值仍然为0;在这里,我们其实是增加了一个实例属性,并没有修改到类属性。

如果我们通过实例a操纵cls_j中的数据(注意不是cls_j本身),又会怎么样呢:

>>> a.cls_j['a'] = 'a'

>>> a.__dict__

{'instance_j': {}, 'cls_i': 1, 'instance_i': 0}

>>> A.__dict__

{'__init__': , '__module__': '__main__', 'cls_i': 0, 'cls_j': {'a': 'a'}, '__doc__': None}

我们可以看到a的作用域没有发生什么变化,但是A的作用域发生了一些变化,cls_j中的数据发生了变化。

实例的作用域发生变化,并不会影响到该类的其它实例,但是类的作用域发生变化,则会影响到该类的所有实例,包括在这之前创建的实例:

>>> A.cls_k = 0

>>> i.cls_k

0
Python 相关文章推荐
Python的ORM框架SQLAlchemy入门教程
Apr 28 Python
Python和Ruby中each循环引用变量问题(一个隐秘BUG?)
Jun 04 Python
NetworkX之Prim算法(实例讲解)
Dec 22 Python
pandas读取CSV文件时查看修改各列的数据类型格式
Jul 07 Python
基于python全局设置id 自动化测试元素定位过程解析
Sep 04 Python
python基于K-means聚类算法的图像分割
Oct 30 Python
Python通过递归获取目录下指定文件代码实例
Nov 07 Python
Python编程快速上手——疯狂填词程序实现方法分析
Feb 29 Python
django项目中新增app的2种实现方法
Apr 01 Python
Python 忽略文件名编码的方法
Aug 01 Python
Python利用机器学习算法实现垃圾邮件的识别
Jun 28 Python
Python 统计序列中元素的出现频度
Apr 26 Python
Python中的作用域规则详解
Jan 30 #Python
Python中使用Boolean操作符做真值测试实例
Jan 30 #Python
Python中的zip函数使用示例
Jan 29 #Python
Python的另外几种语言实现
Jan 29 #Python
python中使用xlrd、xlwt操作excel表格详解
Jan 29 #Python
Python中实现常量(Const)功能
Jan 28 #Python
Python使用random和tertools模块解一些经典概率问题
Jan 28 #Python
You might like
我常用的几个类
2006/10/09 PHP
php读取文件内容至字符串中,同时去除换行、空行、行首行尾空格(Zjmainstay原创)
2012/07/31 PHP
PHP反向代理类代码
2014/08/15 PHP
PHP实现上传文件并存进数据库的方法
2015/07/16 PHP
PHP验证码无法显示的原因及解决办法
2017/08/11 PHP
php静态成员方法和静态的成员属性的使用方法
2017/10/26 PHP
PHP实现类似题库抽题效果
2018/08/16 PHP
jQuery基本过滤选择器使用介绍
2013/04/18 Javascript
javascript获取select的当前值示例代码(兼容IE/Firefox/Opera/Chrome)
2013/12/17 Javascript
node.js中的fs.exists方法使用说明
2014/12/17 Javascript
JavaScript将字符串转换成字符编码列表的方法
2015/03/19 Javascript
jQuery实现限制textarea文本框输入字符数量的方法
2015/05/28 Javascript
js删除Array数组中指定元素的两种方法
2016/08/03 Javascript
JS常见疑难点分析之match,charAt,charCodeAt,map,search用法分析
2016/12/25 Javascript
yii form 表单提交之前JS在提交按钮的验证方法
2017/03/15 Javascript
Angular4学习笔记之新建项目的方法
2017/07/18 Javascript
Windows下快速搭建NodeJS本地服务器的步骤
2017/08/09 NodeJs
详解Vue路由钩子及应用场景(小结)
2017/11/07 Javascript
Vue项目分环境打包的实现步骤
2018/04/02 Javascript
35个最好用的Vue开源库(史上最全)
2019/01/03 Javascript
javascript触发模拟鼠标点击事件
2019/06/26 Javascript
layui表格内放置图片,并点击放大的实例
2019/09/10 Javascript
Python使用Socket(Https)Post登录百度的实现代码
2012/05/18 Python
Python标准库之循环器(itertools)介绍
2014/11/25 Python
关于Python面向对象编程的知识点总结
2017/02/14 Python
教你如何一步一步用Canvas写一个贪吃蛇
2018/10/22 HTML / CSS
HTML5 canvas基本绘图之文字渲染
2016/06/27 HTML / CSS
HTML5播放实现rtmp流直播
2020/06/16 HTML / CSS
Radley英国官网:英国莱德利小狗包
2019/03/21 全球购物
迪士尼英国官方商店:shopDisney UK
2019/09/21 全球购物
乌克兰网上珠宝商店:GoldSoveren
2020/03/31 全球购物
增员口号大全
2014/06/18 职场文书
乡镇党的群众路线教育实践活动剖析材料
2014/10/09 职场文书
初中成绩单评语
2014/12/29 职场文书
PySwarms(Python粒子群优化工具包)的使用:GlobalBestPSO例子解析
2021/04/05 Python
Go中使用gjson来操作JSON数据的实现
2022/08/14 Golang