Python 入门 19 —— 类的属性、 property()

Python 中有三个专门用于装饰类的方法的内置装饰器:property()、classmethod()、staticmethod()。因为这三个装饰器是Python的内置的,所以,其内部的代码是不可见,我们只能了解它们有什么作用,被它们装饰后的类的方法有什么特殊之处。

一、类的属性

@ property 装饰过的类的方法,被称为类的属性。方法变成属性之后,最大的区别就是在引用时,不可以再传递参数,甚至连小括号也不能要了。例如:

class c01:
    @property
    def p01(self): return 100

obj01 = c01()
print(obj01.p01)    # 100
print(obj01.p01())    # TypeError: 'int' object is not callable

使用属性机制主要是为了加强对对象的数据成员的保护。

对象数据成员如果是公开的和保护的,那么就可以随意地访问、修改和删除。如果是私有的,那么就根本无法访问。这两种情况都比较极端:要么随意,要么不可见。那能不能做到既可以访问,又对修改和删除进行一定的检查和限制呢?能,属性机制就是为此而生。例如:

class c02:
    def __init__(self,x=100):self.__v= x

    @ property
    def p01(self): return self.__v

obj02=c02()
print(obj02.p01)    # 通过属性可以访问私有成员:100
print(obj02.__v)    # 不能直接访问私有成员:AttributeError: 'c02' object has no attribute '__v'

obj02.p01=200    # AttributeError: can't set attribute
del obj02.p01    # AttributeError: can't delete attribute

实际上,属性主要就是用于间接地访问和操作对象的私有数据成员。缺省情况下,属性既不能被修改,也不能被删除。不过,通过 property() 函数可以设置访问、修改、删除属性时的魔法函数。

二、property() 函数

通过 property() 函数既可以定义一个属性,同时还可以设置在访问、修改、删除这个属性时的魔法函数。

属性名 = property(访问属性时的魔法函数名, 修改属性时的魔法函数名, 删除属性时的魔法函数名)

例如:

class c03:
    def __p01get(self):print('Get p01')
    def __p01set(self,x=1):print('Set p01')
    def __p01del(self):print('del p01')
    p01=property(__p01get,__p01set,__p01del)    # 定义属性 p01,同时设置操作它时的魔法函数

    def __p02get(self):print('Get p02')
    def __p02set(self,x=1):print('Set p02')
    def __p02del(self):print('del p02')
    p02=property(__p02get,__p02set,__p02del)    # 定义属性 p02,同时设置操作它时的魔法函数

obj03=c03()

obj03.p01    # 访问属性时系统自动调用 __p01get(): Get p01
obj03.p01=200    # 修改属性时系统自动调用 __p01set(): Set p01
del obj03.p01    # 删除属性时系统自动调用 __p01del(): del p01

obj03.p02    # Get p02
obj03.p02=200    # Set p02
del obj03.p02    # del p02

三、通过属性操作私有成员

class c04:
    def __init__(self,x,y):self.__v1= x;self.__v2= y;

    def __p01get(self):return self.__v1

    def __p01set(self,x):
        if x>=10: self.__v1=x; print('Set p01 OK:',self.__v1)
        else: print('Set NO')

    def __p01del(self):del self.__v1; print('p01 Del OK')
    p01=property(__p01get,__p01set,__p01del)    # 通过 p01 可操作私有数据成员 __v1

    def __p02get(self):return self.__v2

    def __p02set(self,x):
        if x<10:self.__v2=x; print('Set p02 OK:',self.__v2)
        else: print('Set NO')

    def __p02del(self): print('p02 Can not Del')
    p02=property(__p02get,__p02set,__p02del)    # 通过 p02 可操作私有数据成员 __v2

obj04=c04(66,88)

print(obj04.p01)   # 66
obj04.p01=5   # 不符合条件不允许修改:Set NO
obj04.p01=15   # 符合条件才允许修改:Set p01 OK: 15
del obj04.p01   # 实际删除的是私有成员:p01 Del OK

print(obj04.p02)   # 88
obj04.p02=5   # Set p02 OK: 5
obj04.p02=15   # Set NO
del obj04.p02   # 不允许删除私有成员:p02 Can not Del
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章