如果 Python 中的内部属性不希望被外部访问,那么就应该在属性名称前加两个下划线。这样,就无法在外部直接访问了。如下:
class Student(object):
def __init__(self, score):
self.__score = score
之后,我们如果直接想通过属性名称调用,就需要使用@property
了:
@property
def score(self):
return self._score
如果这样,要增加不少代码,而调用实例名称.score的结果与不加下划线的结果一致。那么,加两个下划线的目的是什么呢
1
congeec 2017-08-16 00:37:10 +08:00 via iPhone 1
加下划线就是为了让变量 private, 然而你又想在外部访问 private 变量。这让大家很为难呐🤷♂️
|
2
wisej 2017-08-16 00:49:05 +08:00 via Android 1
加下划线一般意味着这个变量是私有的,也就是希望你不要去修改它。
但是,你只加下划线的话,虽然无法直接访问,但是你想的话还是可以访问并修改的!(也就是说,下划线只是一个大家的一个共识,它只对 responsible user 起作用) 但你加上第二段代码后,它内部通过__setattr__方法会拦截你对这个私有变量的修改。也就是从代码层面防止你动手脚了。 这就是两者区别,相当于一个道德约束,一个是法律约束 |
3
iEverX 2017-08-16 00:51:27 +08:00 via Android 1
不能修改
|
4
billwsy 2017-08-16 01:08:43 +08:00 via iPhone 1
@wisej __setattr__并没有阻止对_score 的访问,而是模拟了对 score 的访问,尽管它并不存在
加一个下划线是约定,也就是外部的代码不应该去访问_score ;加两个下划线是强制,外部的代码不能去访问__score (尽管根据混淆规则还是有办法去访问,但是更不直观) 回到问题,加两个下划线的目的是防止外部代码去访问__score,任何对它的读写应该通过成员函数来完成。好处是读写的时候你可以做更多的判断,例如写的时候判断分数是不是在一个范围内,读的时候做校验之类的。而 property 利用 Python 的机制(也就是上面说的__setattr__)实现了更直观的语法,你可以通过 print self.score 来调用 self.score()函数,而它正巧返回了 self.__score 这个成员变量。 |
5
billwsy 2017-08-16 01:15:38 +08:00 via iPhone 1
纠错…上面说的 Python 机制并不是__setattr__,而是 property 对象的__get__
|
6
lxml 2017-08-16 05:19:05 +08:00 1
@wisej #2 set 的作用不应该是拦截,而是类似于装饰器一样的,对传入的值做一些过滤,类型验证是否合法等工作,没问题就放行。
|
7
wisej 2017-08-16 11:57:23 +08:00 1
@lxml @billwsy 嗯。。我错了 @property 内部实现机制是 Descriptor (我一开始以为是用__getattribute__,__setattribute__来实现的... ,但是这样会影响到其他属性访问)
我贴一下我现在的理解,你们看对不,不对望指正: score = property(fget, fset, fdel, docs),会生成一个名为 score 的 Descriptor.这样,当我们访问 Student.score 等于 Student.score.__get__ 。而 __get__ 内部调用了函数 fget。 至于 ``` @property def score(self): return self._score @score.setter def score(self): pass ``` 则是分别调用了 property 的 getter、setter 将对应的函数引用赋值给 fget 和 fset |
8
zhusimaji 2017-08-16 12:00:59 +08:00 1
1、外部实例对象想访问对象成员变量应该是通过 getsatt 方式获取属性
2、楼主使用 @property 修饰 score 函数使其成为属性 3、在外部调用的时候会经历 1、2 两个步骤 4、两个下划线就是私有变量,希望你不要从外部访问,但是你仍然是可以从外部通过某个手段访问,楼主可以试试,没有绝对的私有,只是你这么定义就是遵守约定不要乱来 |
9
wisej 2017-08-16 12:01:27 +08:00 1
|
10
zhusimaji 2017-08-16 12:01:29 +08:00 1
打错了,getattr
|