谈谈Python:为什么类中的私有属性可以在外部赋值并访问


Posted in Python onMarch 05, 2020

Python:为什么类中的私有属性可以在外部赋值并访问?

问题引入

在慕课网上学习Python**类中的私有属性**的时候,看到了一个同学的提问:

将count改为__count,为什么实例变量在外部仍然可以修改__count?这里print p1.__count可以打印出100

class Person(object):
 __count = 0
 def __init__(self, name):
  Person.__count = Person.__count + 1
  self.name = name
  print Person.__count
 p1 = Person('Bob')
 p1.__count=100
 print p1.__count
 p2 = Person('Alice')

print Person.__count

问题解决:

单刀直入版:

这是因为给p1.__count赋值的操作,其实是在p1中定义了一个名为__count的变量(因为Python中的都是动态变量),而没有改变类中真正的属性。

太长但还是要看看版:

知识点清单:

1、类的“伪私有属性”
2、在类的外部动态地创建类属性

问题解决过程:

1、“伪私有属性”的概念:

python的类中通过加双下划线来设置的“私有属性”其实是“伪私有属性”,原理是python编译器将加了双下划线的“属性名”自动转换成“类名属性名”。所以我们在外部用“属性名”访问私有属性的时候,会触发AttributeError,从而实现“私有属性”的特性。但通过“类名属性名”也可以访问这些属性。

参考:http://www.pythonclub.org/python-class/private

2、编写测试代码:

以下是在该同学的代码的基础上修改的测试代码:

class Person(object):
 #设置类属性
 __count_of_class = 'original count_of_class'
 def __init__(self, name):
  self.name = name
  print('in class Person : count_of_class = ', Person.__count_of_class,'\n')

#初始化实例p1
p1 = Person('Bob')
#在实例p1上修改属性值
p1.__count_of_class='I\'m not the original count_of_class!'
print('p1\'s _Person__count_of_class = ',p1._Person__count_of_class)
print('p1\'s __count_of_class = ',p1.__count_of_class,'\n')

#在类Person上修改属性值
Person.__count_of_class = 'I\'m not the original count_of_class!'
#将这句注释取消掉,会发现真正的私有属性的值也改变了
#Person._Person__count_of_class = 'I\'m not the original count_of_class!'
print('Person\'s _Person__count_of_class = ',Person._Person__count_of_class)
print('Person\'s __count_of_class = ',Person.__count_of_class)

分别在实例p1上和类Person上进行操作,并且分别打印出“__属性名”,以及“_类名__属性名”。

输出结果如下:

in class Person : count_of_class = original count_of_class

p1's _Person__count_of_class = original count_of_class
p1's __count_of_class = I'm not the original count_of_class!

Person's _Person__count_of_class = original count_of_class
Person's __count_of_class = I'm not the original count_of_class!

**由此可见,虽然用p1.__count_of_class给它赋值了,但其实在类中真正的属性_Person__count_of_class的原始值是没有改变的。

但是如果将p1._Person__count_of_class赋值,那么类属性定义的原始值就真正地被覆盖了**

"""
取消掉
##Person._Person__count_of_class = 'I\'m not the original count_of_class!'
的注释,输出结果:
"""

in class Person : count_of_class = original count_of_class 
p1's _Person__count_of_class = original count_of_class 
p1's __count_of_class = I'm not the original count_of_class! 

#注意这一句:
Person's _Person__count_of_class = I'm not the original count_of_class! 
Person's __count_of_class = I'm not the original count_of_class!

由此,我们知道了:_count_of_class和_Person_count_of_class不是同一个东西。

最后的问题

但是呢,如果不先给p1.__count_of_class赋值,直接打印它又会触发AttributeError,这是为什么?

这是因为给p1.__count_of_class赋值的操作,其实是在p1中定义了一个名为__count_of_class的变量(因为Python中的都是动态变量)。

以下实例说明可以通过外部赋值来为类创造属性:

class Person(object):
 pass

p1=Person()
#给p1创建属性new_of_instance
p1.new_of_instance = 'I\'m new in p1!'
print(p1.new_of_instance)

#给Person类创建属性new_of_class
Person.new_of_class = 'I\'m new in Person!'

#在类中新加的属性,可以通过实例来访问
print(p1.new_of_class)


>>>输出:
I'm new in p1!
I'm new in Person!

问题解决。

以上这篇谈谈Python:为什么类中的私有属性可以在外部赋值并访问就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中使用装饰器时需要注意的一些问题
May 11 Python
python读取TXT到数组及列表去重后按原来顺序排序的方法
Jun 26 Python
解决Ubuntu pip 安装 mysql-python包出错的问题
Jun 11 Python
Tensorflow使用支持向量机拟合线性回归
Sep 07 Python
PyQt 实现使窗口中的元素跟随窗口大小的变化而变化
Jun 18 Python
python+opencv实现摄像头调用的方法
Jun 22 Python
python tornado使用流生成图片的例子
Nov 18 Python
使用Django搭建网站实现商品分页功能
May 22 Python
python3+opencv 使用灰度直方图来判断图片的亮暗操作
Jun 02 Python
Python如何在windows环境安装pip及rarfile
Jun 15 Python
python编程实现清理微信重复缓存文件
Nov 01 Python
Python调用腾讯API实现人脸身份证比对功能
Apr 04 Python
python如何将两张图片生成为全景图片
Mar 05 #Python
Python 定义只读属性的实现方式
Mar 05 #Python
Pycharm中import torch报错的快速解决方法
Mar 05 #Python
Python中私有属性的定义方式
Mar 05 #Python
Python实现AI自动抠图实例解析
Mar 05 #Python
python GUI库图形界面开发之PyQt5 MDI(多文档窗口)QMidArea详细使用方法与实例
Mar 05 #Python
Python matplotlib修改默认字体的操作
Mar 05 #Python
You might like
php设计模式之单例模式使用示例
2014/01/20 PHP
ThinkPHP采用GET方式获取中文参数查询无结果的解决方法
2014/06/26 PHP
调试PHP程序的多种方法介绍
2014/11/06 PHP
php 使用curl模拟登录人人(校内)网的简单实例
2016/06/06 PHP
Laravel使用swoole实现websocket主动消息推送的方法介绍
2019/10/20 PHP
为jQuery增加join方法的实现代码
2010/11/28 Javascript
Knockout visible绑定使用方法
2013/11/15 Javascript
Javascript实现的简单右键菜单类
2015/09/23 Javascript
JS+CSS实现经典的左侧竖向滑动菜单效果
2015/09/23 Javascript
IE8 内存泄露(内存一直增长 )的原因及解决办法
2016/04/06 Javascript
Vue上传组件vue Simple Uploader的用法示例
2017/08/25 Javascript
JS实现图片拖拽交换效果
2018/11/30 Javascript
小程序实现搜索界面 小程序实现推荐搜索列表效果
2019/05/18 Javascript
node.js中stream流中可读流和可写流的实现与使用方法实例分析
2020/02/13 Javascript
antd Form组件方法getFieldsValue获取自定义组件的值操作
2020/10/29 Javascript
JavaScript实现跟随鼠标移动的盒子
2021/01/28 Javascript
python基础教程之缩进介绍
2014/08/29 Python
python数组过滤实现方法
2015/07/27 Python
Python调用C++程序的方法详解
2017/01/24 Python
Python3.4实现远程控制电脑开关机
2018/02/22 Python
Python实现线程状态监测简单示例
2018/03/28 Python
利用Python小工具实现3秒钟将视频转换为音频
2019/10/29 Python
python GUI库图形界面开发之PyQt5线程类QThread详细使用方法
2020/02/26 Python
使用Dajngo 通过代码添加xadmin用户和权限(组)
2020/07/03 Python
详解Django自定义图片和文件上传路径(upload_to)的2种方式
2020/12/01 Python
用纯css3和html制作泡沫对话框实现代码
2013/03/21 HTML / CSS
美国家用电器和电子产品商店:Abt
2016/09/06 全球购物
捷克玩具商店:Bambule
2019/02/23 全球购物
瑞士隐形眼镜和护理产品网上商店:Linsenklick
2019/10/21 全球购物
几个Shell Script面试题
2012/08/31 面试题
英语专业学生个人求职信
2014/01/28 职场文书
企业诚信承诺书
2014/05/23 职场文书
普通党员四风问题对照检查材料
2014/09/27 职场文书
辞职信格式模板
2015/02/27 职场文书
2015年高三年级组工作总结
2015/07/21 职场文书
七年级作文之下雨天
2019/12/23 职场文书