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处理文本文件并生成指定格式的文件
Jul 31 Python
Python的Tornado框架异步编程入门实例
Apr 24 Python
WINDOWS 同时安装 python2 python3 后 pip 错误的解决方法
Mar 16 Python
对pandas里的loc并列条件索引的实例讲解
Nov 15 Python
Python shutil模块用法实例分析
Oct 02 Python
Python urlopen()和urlretrieve()用法解析
Jan 07 Python
pytorch使用tensorboardX进行loss可视化实例
Feb 24 Python
Python callable内置函数原理解析
Mar 05 Python
python 在threading中如何处理主进程和子线程的关系
Apr 25 Python
python中sympy库求常微分方程的用法
Apr 28 Python
PyTorch-GPU加速实例
Jun 23 Python
python爬虫scrapy基本使用超详细教程
Feb 20 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
深入HTTP响应状态码速查表的详解
2013/06/07 PHP
PHP实现微信提现(企业付款到零钱)
2019/08/01 PHP
getElementById在任意一款浏览器中都可以用吗的疑问回复
2007/05/13 Javascript
angularJS与bootstrap结合实现动态加载弹出提示内容
2015/10/16 Javascript
JS中JSON对象和String之间的互转及处理技巧
2016/04/06 Javascript
浅谈jquery点击label触发2次的问题
2016/06/12 Javascript
jQuery事件用法详解
2016/10/06 Javascript
微信小程序 数据访问实例详解
2016/10/08 Javascript
js 点击a标签 获取a的自定义属性方法
2016/11/21 Javascript
jquery实现输入框实时输入触发事件代码
2016/12/21 Javascript
vue货币过滤器的实现方法
2017/04/01 Javascript
bootstrap fileinput组件整合Springmvc上传图片到本地磁盘
2017/05/11 Javascript
如何去除vue项目中的#及其ie9兼容性
2018/01/11 Javascript
vue cli升级webapck4总结
2018/04/04 Javascript
微信小程序中this.data与this.setData的区别详解
2018/09/17 Javascript
vue 集成jTopo 处理方法
2019/08/07 Javascript
解决vue-cli项目开发运行时内存暴涨卡死电脑问题
2019/10/29 Javascript
vue+高德地图实现地图搜索及点击定位操作
2020/09/09 Javascript
[00:35]可解锁地面特效
2018/12/20 DOTA
python 3利用Dlib 19.7实现摄像头人脸检测特征点标定
2018/02/26 Python
python中实现数组和列表读取一列的方法
2018/04/03 Python
基于Python打造账号共享浏览器功能
2019/05/30 Python
Python3进制之间的转换代码实例
2019/08/24 Python
Python 读取用户指令和格式化打印实现解析
2019/09/02 Python
python 内置函数汇总详解
2019/09/16 Python
使用Python的Turtle绘制哆啦A梦实例
2019/11/21 Python
使用OpenCV-python3实现滑动条更新图像的Canny边缘检测功能
2019/12/12 Python
Python 操作 MySQL数据库
2020/09/18 Python
Python调用REST API接口的几种方式汇总
2020/10/19 Python
英国街头品牌:Bee Inspired Clothing
2018/02/12 全球购物
如何撰写岗位职责
2014/02/01 职场文书
高中军训第一天感言
2014/03/06 职场文书
教师业务培训方案
2014/05/01 职场文书
保护水资源的标语
2014/06/17 职场文书
工厂见习报告范文
2014/10/31 职场文书
劳动仲裁代理词范文
2015/05/25 职场文书