参考自:Python的@property是干嘛的?作者:Python测试开发
如果我们设置类的属性私有化,那么可以使用@property
使属性可以被外部访问并修改。
在使用 @property
之前,需要先了解几个概念。
_age
(单下划线):这种属性表示约定私有,非真正的私有__age
(双下划线):表示私有,外部无法访问__age__
(前后双下划线):这种属性表示系统属性(可选)age_
(后单下划线):这种属性是为了避免和保留关键字冲突。
code01: 自定义学生类
class Student(object): _age = 18 __sex = "man" ming = Student()
可以通过ming._age
访问age的值,但是ming.__sex
就会报错,提示AttributeError: 'Student' object has no attribute '__age'
。
既然私有属性无法访问,那么如何在外部进行访问和查看?
code02: 自定义方法访问私有属性
class Student(object): _age = 18 __sex = "man" def get_sex(self): return self.__sex def set_sex(self, sex): self.__sex = sex ming = Student()
code02中,在Student内自定义了get_sex()
和set_sex()
方法实现对私有属性的访问和修改。
>>> print(ming.get_sex()) 'man' >>> ming.set_sex("woman") >>> ming.get_sex() 'woman'
code03: 使用@property访问私有属性
如果需要暴露的私有属性比较多,使用自定义方法就比较繁琐了。为此,Python提供了@property
,实现同样的功能,并且更方便。
class Student(object): _age = 18 __sex = "man" @property def sex(self): return self.__sex @age.setter def sex(self,sex): self.__sex = sex ming = Student()
code03中,使用@property
直接将__sex
私有属性转变为普通属性。
>>> print(ming.get_sex()) man >>> print(ming.sex) man >>> ming.set_sex("woman") >>> print(ming.sex) woman
可以看到,ming.age
和ming.get_sex()
的结果是一样。
不过@property
只能访问,不能修改。如果要修改,还要配合setter
使用,示例如下:
class Student(object): _age = 18 __sex = "man" @property def sex(self): return self.__sex @sex.setter def sex(self,sex): self.__sex = sex ming = Student()
测试:
>>> print(ming.sex) 'man' >>> ming.age = 20 >>> print(ming.age) 20
emmmm,还算方便。
可能会有些疑问:既然事先要设置私有属性,那为什么还要暴露出去?
个人认为,有些属性设置为私有后,能保证代码安全,而且使用@property
能够统一接口和代码风格,如果属性需要设置只读,那么删掉setter
方法就行了。如果修改属性的时候需要限制,也可以类似于以下方法进行限制:
class Student(object): __age = 18 __sex = "man" @property def sex(self): return self.__sex @sex.setter def sex(self,sex): self.__sex = sex @property def age(self): return self.__age @age.setter def age(self, new_age): if new_age >0 and new_age <= 130: self.__age = new_age else: raise ValueError("[ERROR] Invalid age value!") ming = Student()
上面的代码将age
属性也设置为私有,并且使用@property
公开。通过定义setter
对age的数值进行限制。如果执行ming.age=200
,则将会报错。