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

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

 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_nameget_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 面向对象(二)--访问限制的更多相关文章

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

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

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

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

  3. python面向对象二

    1.1类的静态属性,类方法,类的静态方法 1.1.1静态属性(@property) 在类中: python内置的@property装饰器就是负责把一个方法(函数)变成属性来调用. class Stud ...

  4. python 面向对象二 类和实例

    一.类和实例 面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法, ...

  5. python 面向对象三 访问权限 下划线 双下划线

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

  6. Python 面向对象(二) 特殊方法

    一些Python特殊方法的汇总 __bases__    类的基类,返回元祖__base__  类的基类,也叫父类__call__ '类名()',类名加括号调用时执行的语句__class__ 对象或类 ...

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

    ##################################总结########################### 类的成员: 变量: 实例变量      对象.属性=xxx 类变量    ...

  8. python面向对象(二)

    属性查找 类有两种属性:数据属性和函数属性 1. 类的数据属性是所有对象共享的 2. 类的函数属性是绑定给对象用的 class BeijingStudent:   school='Beijing'  ...

  9. Python 面向对象二(转载)

    来源:www.cnblogs.com/wupeiqi/p/4766801.html 三.类成员的修饰符 类的所有成员在上一步骤中已经做了详细的介绍,对于每一个类的成员而言都有两种形式: 1.公有成员, ...

随机推荐

  1. disruptor 问题排查

    需求:收到银行异步通知,要在2秒内将结果返回银行,同时还要根据银行返回的交易状态更新数据库订单状态和其他业务. 采用disruptor,其实最好使用独立MQ产品.本次用的是disruptor,遇到了一 ...

  2. python中字典排序,列表中的字典排序

    python中字典排序,列表中的字典排序 一.使用python模块:operator import operator #首先要导入模块operator x = {1:2, 3:4, 4:3, 2:1, ...

  3. CSS background-size contain 与cover的区别

    最近在重温CSS,发现好多东西都忘了,比如background-size属性中,contain与cover的区别. 菜鸟教程上是这么说的: 有点难理解,通俗解释就是:两者均以保持图像宽高比的形式缩放来 ...

  4. mgo03_linux7上安装mongo4.0

    下载地址https://www.mongodb.com/download-center#community tar -xvf mongodb-linux-x86_64-rhel70-4.0.0.tgz ...

  5. mpdf Could not find image file (http://local.com/xxxxx)

    记录一下昨天和今天遇到的,yii2使用mpdf的时候,图片是使用php方法生成的二维码,所以图片地址为http://local.com/xxxxx,url中携带不同的参数. 但是开启了 $mpdf-& ...

  6. JavaSE---反射(未完待续)

    1.概述 1.1 Java程序中许多对象在运行时会出现2种类型:编译时类型.运行时类型: eg:Person  person=new Student(); 这行代码在编译时为Person类型,运行时为 ...

  7. Python数据操作

    列表操作 保存matrix或者保存ndarray 数据类型转换 读取CSV某列 numpy数组写入到csv pandas to_csv 最左边 多一列 的问题 DataFrame对象操作

  8. F. Cooking Time 贪心

    http://codeforces.com/gym/101498/problem/F 对于知道使用情况的置换算法,最优解是找一个最后需要使用的物品替换掉 也就是,如果一个物品后面已经不需要用到,就要拿 ...

  9. 性能测试工具Jmeter02-安装配置

    安装配置 1.安装配置jdk 2.Jmeter下载地址:http://mirror.bit.edu.cn/apache/jmeter/binaries/ 下载后,解压文件到任意目录,避免在一个有空格的 ...

  10. avalon教程-简介

    avalon是什么? avalon是一个MVVM框架, Modle-模型层,即为js中从后台接口中取出的数据,例如一个对象或者对象数组,并对这些数据进行一定的格式化.常见的返回数据是这样的{id : ...