<无访问限制的对象>

在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑。但是,从前面Student类的定义来看(见:Python面向对象编程——类定义与对象),外部代码还是可以自由地修改一个实例的namescore属性

  1. >>> bart = Student('Bart Simpson', 98)
  2. >>> bart.score
  3. 98
  4. >>> bart.score = 59
  5. >>> bart.score
  6. 59
 

<增加访问限制>

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

  1. class Student(object):
  2. def __init__(self, name, score):
  3. self.__name = name
  4. self.__score = score
  5. def print_score(self):
  6. print('%s: %s' % (self.__name, self.__score))
 

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

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

这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。但是如果外部代码要获取属性name和score,可以给Student类增加get_nameget_score这样的方法:

  1. class Student(object):
  2. ...
  3. def get_name(self):
  4. return self.__name
  5. def get_score(self):
  6. return self.__score
 

如果又要允许外部代码修改属性score,可以再给Student类增加set_score方法:

  1. class Student(object):
  2. ...
  3. def set_score(self, score):
  4. self.__score = score
 

原先那种直接通过bart.score = 59也可以修改属性,这样大费周章的定义方法来修改属性的目的是为了在传入参数时,可以对参数做检查,避免传入无效的参数:

  1. class Student(object):
  2. ...
  3. def set_score(self, score):
  4. if 0 <= score <= 100:
  5. self.__score = score
  6. else:
  7. raise ValueError('bad score')
 

☢注意

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

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

<访问限制的原理>

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

  1. >>> bart._Student__name
  2. 'Bart Simpson'
 

总的来说就是,Python本身没有任何机制阻止你干坏事,一切全靠自觉。最后注意下面的这种错误写法:

  1. >>> bart = Student('Bart Simpson', 98)
  2. >>> bart.get_name()
  3. 'Bart Simpson'
  4. >>> bart.__name = 'New Name' # 设置__name变量!
  5. >>> bart.__name
  6. 'New Name'
 

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

  1. >>> bart.get_name() # get_name()内部返回self.__name
  2. '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. Django 基础命令

  2. UNIX网络编程 第8章 基本UDP套接字编程

    UDP是无连接的,不需要accept,TCP通过accept API来接受连接,并且将连接客户端的信息写入到accept将返回的新socket中,该新socket中有服务端和客户端的IP地址和端口,因 ...

  3. 85.YCbCr与YUV的区别

    yuv色彩模型来源于rgb模型,该模型的特点是将亮度和色度分离开,从而适合于图像处理领域. YCbCr模型来源于yuv模型,应用于数字视频,ITU-R BT.601 recommendation 通过 ...

  4. 查看gcc的默认宏定义命令【转】

    转自:http://blog.csdn.net/cywosp/article/details/10730931 有些时候我们在编写代码或者阅读开源项目时经常会遇到一些陌生的宏定义,在找遍所有源代码都没 ...

  5. C#中HttpWebRequest的GetRequestStream执行的效率太低,甚至偶尔死掉

    为了提高httpwebrequest的执行效率,查到了一些如下设置 request.ServicePoint.Expect100Continue = false; request.ServicePoi ...

  6. Unity教程之-Unity3d中针对Android Apk的签名验证(C#实现)

    当Unity开发的游戏以Android Apk的形式发布之后,经常会遇到的一种情况就是别人对我们的游戏进行二次打包,也就是用他们的签名替换掉我们的签名,从而堂而皇之的将胜利果实占为己有.面对这样的情况 ...

  7. http://s22.app1105796624.qqopenapp.com/

    http://s22.app1105796624.qqopenapp.com/ http://121.43.114.69/xiyou/app/js/ac_tx.js http://hiyouba.co ...

  8. J2V8 For Android

    J2V8是基于Google的JavaScript引擎V8的Java开源项目,实现Java和JavaScript的相互调用.并对Android平台提供支持,最新版本提供了aar格式的类库包方便Andro ...

  9. IOS使用xcode编译代码

    一.安装xcode 在app store中搜索xcode然后点击安装即可. 二.创建第一个app 1.启动xcode,单击Lauchpad 2.单击xcode启动 3.单击“Create a new ...

  10. asterisk各种报错

    1.控制台打印出: Got SIP response "Temporarily Unavailable" back from 210.13.87.110:5060   造成原因:在 ...