<无访问限制的对象>

在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑。但是,从前面Student类的定义来看(见:Python面向对象编程——类定义与对象),外部代码还是可以自由地修改一个实例的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本身没有任何机制阻止你干坏事,一切全靠自觉。最后注意下面的这种错误写法:

>>> 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'
 

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

 
 
 
 

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

  1. python 面向对象编程学习

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

  2. python 面向对象编程(一)

    一.如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法. 类是对现实世界中一些事物的封装,定义一个类可以采用下面的方式来定义: class c ...

  3. Python面向对象编程指南

    Python面向对象编程指南(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1SbD4gum4yGcUruH9icTPCQ 提取码:fzk5 复制这段内容后打开百度网 ...

  4. python面向对象编程进阶

    python面向对象编程进阶 一.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 1 ...

  5. Python面向对象编程(下)

    本文主要通过几个实例介绍Python面向对象编程中的封装.继承.多态三大特性. 封装性 我们还是继续来看下上文中的例子,使用Student类创建一个对象,并修改对象的属性.代码如下: #-*- cod ...

  6. Python 面向对象编程基础

    Python 面向对象编程基础 虽然Pthon是解释性语言,但是Pthon可以进行面向对象开发,小到 脚本程序,大到3D游戏,Python都可以做到. 一类: 语法: class 类名: 类属性,方法 ...

  7. python面向对象编程学习

    python面向对象编程 基本概念理解 面向对象编程--Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作 ...

  8. 图解python | 面向对象编程

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/56 本文地址:http://www.showmeai.tech/article-det ...

  9. Python 面向对象编程 继承 和多态

    Python 面向对象编程 继承 和多态 一:多继承性 对于java我们熟悉的是一个类只能继承一个父类:但是对于C++ 一个子类可以有多个父亲,同样对于 Python一个类也可以有多个父亲 格式: c ...

随机推荐

  1. 一段鬼畜风格的JavaScript解密

    在CSDN上看到有人提问一段JS怎么解密,虽然已经是四年前的问题了,还是解一下. 原问题地址: 这段JS怎样解密? [问题点数:40分,结帖人seo2014] 这是楼主发出的原JS: /*ZlQEIn ...

  2. Grunt、gulp、webpack、不要听着高大上你就上,试试Codekit?

    下载地址:https://incident57.com/codekit/ 官方网站了解更多 要编译Less.Sass.Stylus, CoffeeScript, Typescript, Jade, H ...

  3. RPC简介与hdfs读过程与写过程简介

    1.RPC简介 Remote Procedure Call 远程过程调用协议 RPC——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC协议假定某些 ...

  4. Method for balancing binary search trees

    Method for balancing a binary search tree. A computer implemented method for balancing a binary sear ...

  5. 通过PDB文件实现非嵌入式的c++反射

    上一篇blog我阐述了一种实现非嵌入式的反射的基本思路.相比于通过宏和模板实现,这种非嵌入的反射的优点是不需要写额外的代码来记录meta信息. 首先,为了在c++中实现反射系统,我认为需要解决以下两个 ...

  6. Vue起步

    Vue起步 Vue.js是什么 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式javascript框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用. ...

  7. linux limits研究

    ---------------------------------------------------------------------------------------------------- ...

  8. [HBase]region split流程

    1. 简介 HBase 的最小管理单位为region,region会按照region 分裂策略进行分裂. 基于CDH5.4.2 2. 总览

  9. 【前端开发】前端引入公共部分footer header的几种方法,及iframe自适应高度js

    一.引入页面几种方法   1.IFrame引入,看看下面的代码    <iframe   frameborder=0   border=0   width=300   height=300    ...

  10. java基础23 Math类和Random类

    一.Math数学类 主要是提供很多数学的公式 1.1.Math类的常用方法 abs(int a):绝对值   ceil(double a):向上取整   floor(double a):向下取整   ...