在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. 4-----Scrapy框架中选择器的用法

    Scrapy提取数据有自己的一套机制,被称作选择器(selectors),通过特定的Xpath或者CSS表达式来选择HTML文件的某个部分Xpath是专门在XML文件中选择节点的语言,也可以用在HTM ...

  2. hadoop 常用hdfs命令

  3. liunx ssh

    ssh-keygen -t rsa 生成创建公匙 ssh username@ip 连接远程服务器

  4. Java基本语法_循环练习系列(二)——万年历

    写万年历大致可以分为以下几个步骤: 1.根据用户输入的年份判断该年是否是闰年. 2.根据用户输入的月份计算该月的天数. 3.计算输入的年份之前的总天数. 4.计算输入的月份之前的天数. 5.计算该月的 ...

  5. 关于老教授之家项目的思考 && 中国互联网+大赛培训

    最近在做中国互联网+竞赛相关的项目,有一点思考在这里记录下来,算是一份经历,日后可以再回顾,这也是我真正参加的一个大型比赛,作为技术人员可能更多的是从事技术,但是在其他方面能贡献自己的一份力量也是不错 ...

  6. 使用mspaint查看图片像素

    图片打码服务,要求对图像验证码进行切图,即具体知道像素的位置,网上搜了yhb-chi但下载不方便. 就想着看看mspaint可不可以,将图片拖到mspaint中: 显示了整张图片的像素大小(100X4 ...

  7. python 在windows下监听键盘按键

    python 在windows下监听键盘按键 使用到的库 ctypes(通过ctypes来调用Win32API, 主要就是调用钩子函数) 使用的Win32API SetWindowsHookEx(), ...

  8. CentOS 搭建Redis4 环境

    下载 wget http://download.redis.io/releases/redis-4.0.10.tar.gz   安装步骤 tar xvf redis-4.0.10.tar.gz mak ...

  9. 文件选择之OpenFileDialog控件

    OpenFileDialog控件主要用于选择要打开的文件,在使用时可以在属性面变中设置属性,也可在代码中设置其属性 OpenFileDialog控件的属性 InitialDirectory 对话框的初 ...

  10. Linux访问https报错

    今天用Linux(CentOS)拉Git仓库时,报了个错unable to access 'https://github.com/Wind4/vlmcsd.git/': SSL connect err ...