python基础——访问限制

  

  在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑

  但是,从前面Student类的定义来看,外部代码还是可以自由地修改一个实例的namescore属性:

>>> bart = Student('Bart Simpson', 98)
>>> bart.score
98
>>> bart.score = 59
>>> bart.score
59

  如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__在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))

  改完后,对于外部代码来说,没什么变动,但是已经无法从外部访问实例变量.__name实例变量.__score了:

>>> bart = Student('Bart Simpson', 98)
>>> bart.__name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__name'

  这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮

   但是如果外部代码要获取name和score怎么办?可以给Student类增加get_nameget_score这样的方法:

class Student(object):
... def get_name(self):
return self.__name def get_score(self):
return self.__score

  如果又要允许外部代码修改score怎么办?可以再给Student类增加set_score方法:

class Student(object):
... def set_score(self, score):
self.__score = score

  你也许会问,原先那种直接通过bart.score = 59也可以修改啊,为什么要定义一个方法大费周折?因为在方法中,可以对参数做检查,避免传入无效的参数

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变量:

>>> bart._Student__name
'Bart Simpson'

  但是强烈建议你不要这么干,因为不同版本的Python解释器可能会把__name改成不同的变量名

  总的来说就是,Python本身没有任何机制阻止你干坏事,一切全靠自觉

  最后注意下面的这种错误写法:

>>> bart = Student('Bart Simpson', 98)
>>> bart.get_name()
'Bart Simpson'
>>> bart.__name = 'New Name' # 设置__name变量!
>>> bart.__name
'New Name'

  表面上看,外部代码“成功”地设置了__name变量,但实际上这个__name变量和class内部的__name变量不是一个变量!内部的__name变量已经被Python解释器自动改成了_Student__name,而外部代码给bart新增了一个__name变量。不信试试:

>>> bart.get_name() # get_name()内部返回self.__name
'Bart Simpson'

完整代码:

#python 访问限制     示例
#2016-8-29 15:06:58
#MengmengCoding
# -*- coding: utf-8 -*- 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 set_score(self,score):
if 0<=score<=100:
self.__score=score
else:
raise ValueError('bad score') def get_grade(self):
if self.__score>=90:
return 'A'
elif self.score>=60:
return 'B'
else:
return 'C'
bart=Student('Bart Simpson',59)
print('bart.get_name()=',bart.get_name()) #获取名字
print('bart.get_score()=',bart.get_score()) #获取分数
bart.set_score(66) #修改分数
print('bart.get_score()=',bart.get_score()) #再次获取分数 #Python解释器对外把__name变量改成了_Student__name,所以,
#仍然可以通过_Student__name来访问__name变量
#但建议不要这么干
print('DO NOT use bart._Student__name:',bart._Student__name)

最新文章

  1. Linux下的一个图形管理工具webmin
  2. js注入
  3. jquery模板制作左侧导航组件
  4. Selenium2学习-005-WebUI自动化实战实例-003-三种浏览器(Chrome、Firefox、IE)启动脚本源代码
  5. scp 传文件
  6. NGUI 3.5教程(六)Font字体
  7. 用Less循环生成样式
  8. VC中的Attach和Detach
  9. BZOJ 3223 Tyvj 1729 文艺平衡树(Splay)
  10. SQL图像查看器 —— SQL Image Viewer
  11. json接口返回值
  12. sql server 分组,取每组的前几行数据
  13. Confluence 6 Oracle 驱动输入你的数据库细节
  14. Azkaban
  15. 大数据学习笔记02-HDFS-常用命令
  16. Could not allocate 40960 bytes percpu data
  17. springboot中定时任务
  18. QueryPerformanceFrequency
  19. C语言基础课第四次作业
  20. Windows命令行参数(不断更新)

热门文章

  1. linux C之getchar()非阻塞方式
  2. 如何在CentOS 7上安装EPEL源
  3. 总结一下classpath
  4. 将一个div始终定位在屏幕中心
  5. JAVA设计模式 之 观察者模式
  6. C 语言 typedef
  7. iOS开发——UI进阶篇(十)导航控制器、微博详情页、控制器的View的生命周期
  8. ios本地化多语言支持
  9. 简述JavaScript函数节流
  10. aspcms标签