因为它涉及了两个东西
1.面对对象的封装
2.python的装饰器思想
面向对象里面,一般是只提供方法去操作对象的属性,而不是直接操作。所以对任意一个熟悉,一般都有对于的getxx()和setxx()方法,意思是指获取某个属性的值和设置某个属性的值。
装饰器的意思是对原有函数,多做点事。它本质上也是一个函数,只不过输入是函数,返回的也是函数,只是在中间会多做点其他事情,这里会涉及到一个闭包的概念。
所以python的property,就是简化了用户需要设置或者获取某个属性的时候,需要知道getxx()和setxx()之类的函数,直接把对象的某个属性傻瓜式操作了,通过对象,直接对某个赋值,取值就行。
python的内置函数built-in function是指在标准库standard library中的内置函数。这些函数不属于任何类或模块,可以直接调用,可以看成python语言不可分割的一部分吧。近似于关键字。abs()
dict()
help()
min()
setattr()
all()
dir()
hex()
next()
slice()
any()
divmod()
id()
object()
sorted()
ascii()
enumerate()
input()
oct()
staticmethod()
bin()
eval()
int()
open()
str()
bool()
exec()
isinstance()
ord()
sum()
bytearray()
filter()
issubclass()
pow()
super()
bytes()
float()
iter()
print()
tuple()
callable()
format()
len()
property()
type()
chr()
frozenset()
list()
range()
vars()
classmethod()
getattr()
locals()
repr()
zip()
compile()
globals()
map()
reversed()
__import__()
complex()
hasattr()
max()
round()
delattr()
hash()
memoryview()
set()
标准库中其他模块内的静态方法等不属于内置函数。
用户自定义扩充的函数也不属于内置。
=============
但在其他语言、其他环境下,内置函数的具体含义不同。
内置函数在概念上并没有唯一专指,是合成词,最好理解为“被内置了的一些函数”
不是使用property才要私有的,而是为了调用私有方法方便,才使用property的,具体请看下面的详解
在绑定属性时,如果直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改:
s = Student()s.score = 9999
这显然不合逻辑。为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数:
class Student(object):def get_score(self):
return self._score
def set_score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
现在,对任意的Student实例进行操作,就不能随心所欲地设置score了:
>>> s = Student()>>> s.set_score(60) # ok!
>>> s.get_score()
60
>>> s.set_score(9999)
Traceback (most recent call last):
...
ValueError: score must between 0 ~ 100!
但是,上面的调用方法又略显复杂,没有直接用属性这么直接简单。
有没有既能检查参数,又可以用类似属性这样简单的方式来访问类的变量呢?对于追求完美的Python程序员来说,这是必须要做到的!
还记得装饰器(decorator)可以给函数动态加上功能吗?对于类的方法,装饰器一样起作用。Python内置的@property装饰器就是负责把一个方法变成属性调用的:
class Student(object):
@propertydef score(self):
return self._score
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
@property的实现比较复杂,先考察如何使用。把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,就拥有一个可控的属性操作:
>>> s = Student()>>> s.score = 60 # OK,实际转化为s.set_score(60)
>>> s.score # OK,实际转化为s.get_score()
60
>>> s.score = 9999
Traceback (most recent call last):
...
ValueError: score must between 0 ~ 100!
注意到这个神奇的@property,在对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过getter和setter方法来实现的。
还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性:
class Student(object):@property
def birth(self):
return self._birth
@birth.setter
def birth(self, value):
self._birth = value
@property
def age(self):
return 2014 - self._birth
上面的birth是可读写属性,而age就是一个只读属性,因为age可以根据birth和当前时间计算出来。
一句话总结
@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。