关于Python的property怎么理解呢? 老是理解不了

Python020

关于Python的property怎么理解呢? 老是理解不了,第1张

这个,没编程经验的人确实难理解。。。

因为它涉及了两个东西

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):

   @property

    def 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广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。