在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. 001 Two Sum 两个数的和为目标数字

    Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...

  2. 安装Python + Selenium

    1.Python下载与安装‍ 先去Python官网下载安装包:http://www.python.org/ 下载后按步骤安装(最好不要安装到系统盘) 安装好后将安装路径(Python和Scripts) ...

  3. zabbix--高级篇-监控docker服务(一)

    一,配置zabbix 客户端环境 rpm -ivh https://mirrors.aliyun.com/zabbix/zabbix//x86_64/zabbix-release-.el7.noarc ...

  4. vue router-link 添加在定义事件

    在vue学习中遇到给router-link 标签添加事件@click .@mouseover等无效的情况 我想要做的是v-for遍历出来的选项卡, 鼠标移上去出现删除标签,移除标签消失的效果 原代码: ...

  5. 关于Vim 的插件snipmate 以及它的安装方式

    在网上看了http://study.163.com/course/courseMain.htm?courseId=269016#/courseMain   里关于snipmate 的视频 snipma ...

  6. springmvc+mybatis+sql server实现简单登录功能

    一.源码: 1.Users.java package com.login.entity; import java.io.Serializable; public class Users impleme ...

  7. 【转】jsoup的使用

     Jsoup的使用   jsoup 是一款 Java 的HTML 解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS以及类似于JQuery的操作方法 ...

  8. Python常用模块一

    一. os模块 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前脚本工作目录:相当于shell下cd ...

  9. 利用自定义特性实现List的多属性排序

    知道linq有order by的功能,但是还是动手研究了一下,算是多实践实践反射.这篇算是笔记,直接上代码: using System; using System.Collections.Concur ...

  10. hystrix应用介绍(四)

    前几章已经讲了hystrix的应用场景,以及如何使用,本章我们针对如何进行hystrix参数配置做一些分析 //异步的执行 @HystrixCommand(groupKey = "testK ...