python 面向对象(二)--访问限制
在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑。
但是,从前面Student类的定义来看,外部代码还是可以自由地修改一个实例的name、score属性:
 class Student(object):
     def __init__(self, name, score):
         self.name = name
         self.score = score
     def print_score(self):
         print('%s: %s' % (self.name, self.score))
 instance = Student('Andy', 60)  # 类的实例
 print(instance.name)
 print(instance.score)
如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问,所以,我们把Student类改一改:
 class Student(object):
     def __init__(self, name, score):
         self.__name = name
         self.__score = score
     def print_score(self):
         print('%s: %s' % (self.__name, self.__score))
 instance = Student('Andy', 60)  # 类的实例
 print(instance.name)
 会提示:
       AttributeError: 'Student' object has no attribute 'name'
改完后,对于外部代码来说,没什么变动,但是已经无法从外部访问实例变量.__name和实例变量.__score了,这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。
但是如果外部代码要获取name和score怎么办?可以给Student类增加get_name和get_score这样的方法:
 class Student(object):
     def __init__(self, name, score):
         self.__name = name
         self.__score = score
     def get_name(self):
         return self.__name
     def get_score(self):
         return self.__score
     def print_score(self):
         print('%s: %s' % (self.__name, self.__score))
 instance = Student('Andy', 60)  # 类的实例
 print(instance.get_name())
但倘若又要允许外部代码修改score怎么办?可以再给Student类增加set_score方法:
class Student(object):
... def set_score(self, score):
self.__score = score
你也许会问,原先那种直接通过instance.score = 60也可以修改啊,为什么要定义一个方法大费周折?因为在方法中,可以对参数做检查,避免传入无效的参
class Student(object):
... def set_score(self, score):
if 0 <= score <= 100:
self.__score = score
else:
raise ValueError('bad score')
需要注意的是,在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__name__、__score__这样的变量名。
有些时候,你会看到以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。
双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量:
print(instance._Student__name) 结果:Andy
但是强烈建议你不要这么干,因为不同版本的Python解释器可能会把__name改成不同的变量名。
总的来说就是,Python本身没有任何机制阻止你干坏事,一切全靠自觉。
最后注意下面的这种错误写法:
 instance = Student('Andy', 60)  # 类的实例
 print(instance.get_name())
 instance.__name='new Name'
 print(instance.__name)
 result:
 Andy
 new Name
 [Finished in 0.1s]
表面上看,外部代码“成功”地设置了__name变量,但实际上这个__name变量和class内部的__name变量不是一个变量!内部的__name变量已经被Python解释器自动改成了_Student__name,而外部代码给bart新增了一个__name变量。
python 面向对象(二)--访问限制的更多相关文章
- python面向对象(二)——类成员
		
Python面向对象 类成员 1.字段 普通字段 属于对象 静态字段 属于类 2.方法 普通方法 触发者是对象 括号里至少一个参数 se ...
 - Python 面向对象编程——访问限制
		
<无访问限制的对象> 在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑.但是,从前面Student类的定义来看(见:Py ...
 - python面向对象二
		
1.1类的静态属性,类方法,类的静态方法 1.1.1静态属性(@property) 在类中: python内置的@property装饰器就是负责把一个方法(函数)变成属性来调用. class Stud ...
 - python 面向对象二 类和实例
		
一.类和实例 面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法, ...
 - python 面向对象三 访问权限 下划线 双下划线
		
一.双下划线 如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问. ...
 - Python 面向对象(二) 特殊方法
		
一些Python特殊方法的汇总 __bases__ 类的基类,返回元祖__base__ 类的基类,也叫父类__call__ '类名()',类名加括号调用时执行的语句__class__ 对象或类 ...
 - python 面向对象(二)成员
		
##################################总结########################### 类的成员: 变量: 实例变量 对象.属性=xxx 类变量 ...
 - python面向对象(二)
		
属性查找 类有两种属性:数据属性和函数属性 1. 类的数据属性是所有对象共享的 2. 类的函数属性是绑定给对象用的 class BeijingStudent: school='Beijing' ...
 - Python 面向对象二(转载)
		
来源:www.cnblogs.com/wupeiqi/p/4766801.html 三.类成员的修饰符 类的所有成员在上一步骤中已经做了详细的介绍,对于每一个类的成员而言都有两种形式: 1.公有成员, ...
 
随机推荐
- Web开发中FormData对象的使用
			
参考: FormData 对象的使用 - Web API 接口 | MDN
 - 在MD中使用Emoji
			
mark语法中支持emoji表情 具体语法是:emoji: 比如我输入 :smile: 就会出现微笑
 - B树与B+
			
简单剖析B树(B-Tree)与B+树https://blog.csdn.net/z_ryan/article/details/79685072 B树和B+树的插入.删除图文详解https://www. ...
 - vue中methods函数调用methods函数写法
			
export default { data() { return { hello:"你好" } }, methods:{ open(that) { that.hello = &qu ...
 - 异地clone RAC数据库 +ASM USE RMAN
			
###sample 如何在本地生成数据库的备份,并复制到DG库新环境(高级) 1. 首先确定本地文件系统(存放备份集)足够大,可以使用如下语句查询当前数据库实际的使用总大小 Rman 备份进度: se ...
 - Google Chrome实用插件
			
Tempermonkey 打开上面的链接需要KXSW_VPN_FQ,下面提供国内获取方式 下载 Tempermonkey_4.7 [提取码:7019]并解压 打开C:\Users\%USERNAME% ...
 - https Android 5.0 以下TLS 版本过低造成的问题
			
异常如下 javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ...
 - 20181031 temp
			
https://wiki.jenkins.io/display/JENKINS/M2+Release+Plugin https://issues.jenkins-ci.org/browse/JENKI ...
 - 【C】一个读取文件记录器
			
分享一下!!! #include<stdio.h> #include<windows.h> #define N 70000 //定义行数!!用空间换取时间 struct stu ...
 - maya2017安装失败如何卸载重装
			
AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...