在Class内部,可以有字段,方法和属性,而外部代码可以通过直接调用实例变量的方法来操作数据,

(1)私有普通字段

比如对于下面的Student类,name字段可以在外面通过对象进行直接访问:

 class Student(object):
def __init__(self, name):
self.name = name def get_name(self):
return self.name rob = Student("Rob")
rob.name = 'Rob1'
print(rob.get_name())

上面的程序输出是 Rob1

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问,所以,我们把Student类改一改:

 class Student(object):
def __init__(self, name):
self.__name = name def get_name(self):
return self.__name rob = Student("Rob")
rob.__name = 'Rob1'
print(rob.get_name())

改完后,对于外部代码来说,没什么变动,但是已经无法从外部访问实例变量.__name,我们看到程序输出是 Rob ,也就是代码 rob.__name = 'Rob1' 并不生效。

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

但是如果外部代码要修改name怎么办?可以给Student类增加set_name这样的方法:

 class Student(object):
... def set_name(self, name):
self.__name = name

你也许会问,原先那种直接通过rob.name= "Rob1"也可以修改啊,为什么要定义一个方法大费周折?因为在方法中,可以对参数做检查,避免传入无效的参数,比如我们想对学生类的score操作:

 class Student(object):
... def get_score(self):
return self.__score def set_score(self, value):
if 0 <= value <= 100:
self.__score = value
else:
raise ValueError("Bad score")

需要注意的是,在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__name__、__score__这样的变量名。

有些时候,你会看到以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。

双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量

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

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

还有一个问题需要注意,

假如有子类继承了Student类,那么private字段能否在子类中访问呢?我们来看下面的例子,Freashman类继承Student类,在Freashman类中尝试获取__score属性:

 class Student(object):
def __init__(self, name):
self.__name = name
self.__score = 0 def get_name(self):
return self.__name def set_name(self, name):
self.__name = name def get_score(self):
return self.__score def set_score(self, value):
if 0 <= value <= 100:
self.__score = value
else:
raise ValueError("Bad score") class Freshman(Student):
def get_score(self):
return self.__score mary = Freshman("Mary")
print(mary.get_score())

运行程序将报错: AttributeError: 'Freshman' object has no attribute '_Freshman__score'

因此私有成员除了类本身内部,其他地方都不可访问。

(2)私有静态字段

我们知道类除了有普通字段,还有静态字段,对于静态字段我们也可以限制只在类内部访问,只是和普通字段稍有不同:

(1)静态字段通过类访问

(2)可以将内部访问的方法设置为静态方法:

 class Student(object):
__nationality = 'China' ... @staticmethod # 静态方法
def get_nationality():
return Student.__nationality # 通过类访问 @staticmethod # 静态方法
def set_nationality(nation):
Student.__nationality = nation # 通过类访问 print(Student.get_nationality())
Student.set_nationality('USA')
print(Student.get_nationality())

方法、属性的访问于上述方式相似,即:私有成员只能在类内部使用

Python面向对象-访问限制的更多相关文章

  1. Python面向对象-访问权限public和private

    上一节我们介绍了,Class内部可以有属性和方法,外部代码通过直接调用实例的方法来操作数据,这样就可以隐藏内部的逻辑实现:同时,外部代码还是可以自由的修改实例的属性和增加方法. 但是有时候,我们不想这 ...

  2. Python 面向对象编程——访问限制

    <无访问限制的对象> 在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑.但是,从前面Student类的定义来看(见:Py ...

  3. python面向对象进阶(八)

    上一篇<Python 面向对象初级(七)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...

  4. python 面向对象(进阶篇)

    上一篇<Python 面向对象(初级篇)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...

  5. python 面向对象编程学习

    1. 问题:将所有代码放入一个py文件:无法维护 方案:如果将代码才分放到多个py文件,好处: 1. 同一个名字的变量互相不影响 2.易于维护 3.引用模块: import module 2.包:解决 ...

  6. python 面向对象学习

    ------Python面向对象初 下面写一个类的简单实用,以便方便理解类 #python 3.5环境,解释器在linux需要改变 #阅读手册查询readme文件 #作者:S12-陈金彭 class ...

  7. python面向对象(二)——类成员

    Python面向对象    类成员 1.字段         普通字段    属于对象         静态字段    属于类   2.方法 普通方法   触发者是对象    括号里至少一个参数 se ...

  8. Python开发【第七篇】:面向对象 和 python面向对象进阶篇(下)

    Python开发[第七篇]:面向对象   详见:<Python之路[第五篇]:面向对象及相关> python 面向对象(进阶篇)   上一篇<Python 面向对象(初级篇)> ...

  9. [Python学习笔记][第六章Python面向对象程序设计]

    1月29日学习内容 Python面向对象程序设计 类的定义与使用 类定义语法 使用class关键词 class Car: def infor(self): print("This is ca ...

随机推荐

  1. ios下引用MUI后input不能输入,Android端正常

    原因是mui框架的有个css样式 *{ -webkit-user-select: none; } 其作用是禁掉用户可以选中页面中的内容. 添加以下style样式即可 input{ -webkit-us ...

  2. 『C++』Temp_2018_12_06

    #include <iostream> #include <string> using namespace std; class Type{ public: string Na ...

  3. MYSQL 8.0.11 安装过程及 Navicat 链接时遇到的问题

    参考博客:https://blog.csdn.net/WinstonLau/article/details/78666423 我的系统和软件版本是这样的: 系统环境:win7.64位 MySQL版本: ...

  4. Python Monitoring UPS with SNMPWALK

    ##Background My co-worker told me he needed to monitor UPS with SNMP module but he only can get hexa ...

  5. layer父界面调用子弹窗的方法和获取子弹窗的元素值总结

    layer.open({ type: 2 ,title: false //不显示标题栏 ,closeBtn: false ,area: ['460px', '45%'] ,shade: 0.5 ,id ...

  6. PHP文档生成器(PHPDoc)的基本用法

    目录 PHP文档生成器(PHPDoc)的基本用法 PHPDoc概述 安装 PHPDoc注释规范 页面级别的注释 代码级别的注释 生成API文档 额外软件 PHP文档生成器(PHPDoc)的基本用法 P ...

  7. MySQL:数据存在则更新,不存在则插入

    前提:表结构存在主键或唯一索引,插入数据包含主键或唯一索引而导致记录重复插入失败. 单条记录更新插入: ,,) ,b,c; 多条记录批量更新插入: ,,),(,,) ON DUPLICATE KEY ...

  8. 农民工自学java到找到工作的前前后后

    我是一名地地道道的农民工,生活在经济落后的农村,有一个哥哥和一个弟弟,父母都是地道的农民,日出而作,日落而息,我从小到大学习一直很好,从小学到高一都,成绩在全级一直名列前茅,这样我也顺利了考上省的重点 ...

  9. player视频.js

    var playStatus = 'pending'; var html_a = '<div class="weui-dialog__bd" id="lly_dia ...

  10. Python学习笔记八:文件操作(续),文件编码与解码,函数,递归,函数式编程介绍,高阶函数

    文件操作(续) 获得文件句柄位置,f.tell(),从0开始,按字符数计数 f.read(5),读取5个字符 返回文件句柄到某位置,f.seek(0) 文件在编辑过程中改变编码,f.detech() ...