property装饰器
python的@property是python的一种装饰器,是用来修饰方法的。
作用:
我们可以使用@property装饰器来创建只读属性,@property装饰器会将方法转换为相同名称的只读属性,可以与所定义的属性配合使用,这样可以防止属性被修改。
使用场景:
1.修饰方法,是方法可以像属性一样访问。
class DataSet(object):
@property
def method_with_property(self): ##含有@property
return 15
def method_without_property(self): ##不含@property
return 15
l = DataSet()
# 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。
print(l.method_with_property)
#没有加@property , 必须使用正常的调用方法的形式,即在后面加()
print(l.method_without_property())
如果使用property进行修饰后,又在调用的时候,方法后面添加了(), 那么就会显示错误信息:TypeError: 'int' object is not callable,也就是说添加@property 后,这个方法就变成了一个属性,如果后面加入了(),那么就是当作函数来调用,而它却不是callable(可调用)的。
2.与所定义的属性配合使用,这样可以防止属性被修改。
由于python进行属性的定义时,没办法设置私有属性,因此要通过@property的方法来进行设置。这样可以隐藏属性名,让用户进行使用的时候无法随意修改。
class DataSet(object):
def __init__(self):
self._images = 1
self._labels = 2 #定义属性的名称
@property
def images(self): #方法加入@property后,这个方法相当于一个属性,这个属性可以让用户进行使用,而且用户有没办法随意修改。
return self._images
@property
def labels(self):
return self._labels
l = DataSet()
#用户进行属性调用的时候,直接调用images即可,而不用知道属性名_images,因此用户无法更改属性,从而保护了类的属性。
print(l.images) # 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。
setter装饰器
为了可以修改x,我们把x的值1写成实例属性self.num,
当然这个例子中外部也可以直接通过修改num的值来修改x的值,不过这个不要紧,因为只是为了方便理解,
实际使用中我们可以把self.num 写成私有属性,来保障不会被外部直接修改值,
写一个x属性同名方法,并且用x属性同名的setter装饰器(x.setter)来装饰同名方法x,然后在这个方法下实现对self.num的值的修改:
class Num:
def __init__(self):
self.num = 1
@property
def x(self):
return self.num
@x.setter
def x(self, item):
self.num = item
@property
def y(self):
return 2
def printf(self):
print(f'{self.x}加{self.y}的和是:{self.x+self.y}')
a = Num() # 把C实例化,命名为a
a.x = 2
a.printf()
deleter装饰器
同setter装饰器,不再详细说明,不同的地方在于被deleter装饰的同名x方法不接收参数,因为我们只是删除了self.num,不需要接收参数:
class Num:
def __init__(self):
self.num = 1
@property
def x(self):
return self.num
@x.setter
def x(self, item):
self.num = item
@x.deleter
def x(self):
del self.num
@property
def y(self):
return 2
def printf(self):
print(f'{self.x}加{self.y}的和是:{self.x+self.y}')
a = Num() # 把C实例化,命名为a
a.x = 2
a.printf()
del a.x
print(a.x)
deleter装饰器装饰的方法就可以被使用del 来删除对应的属性,删除属性的操作我们就再同名方法x中进行了实现,
这样外部删除属性的方法也和删除一个属性的方法保持一致,同样保证了高可用性和可读性。
总结
使用property装饰器装饰的方法可以被上层以调用属性的方式来调用,类本身也可以,可以理解为property属性,也是一个属性;
使用property属性同名.setter装饰器装饰的同名方法,提供property=xx 的方法;
使用property属性同名.deleter装饰器装饰的同名方法,提供del xx的方法。
另外,重要的一点是既然我们已经使用property来代替实例属性,那自然我们是不希望外层可以直接修改实例属性的,
既然如此我们就最好不能使用上述例子中使用的self.num的命名方式来定义实例属性,而是使用私有属性的方式来定义(关于私有属性的知识点可以查看文章开头的相关知识点):
class Num:
def __init__(self):
self.__num = 1
@property
def x(self):
return self.__num
@x.setter
def x(self, item):
if isinstance(item, int):
self.__num = item
else:
print('不要把非int类型赋值给x!!!')
@x.deleter
def x(self):
if self.__num:
del self.__num
else:
print('属性不存在')
@property
def y(self):
return 2
def printf(self):
print(f'{self.x}加{self.y}的和是:{self.x+self.y}')
a = Num() # 把C实例化,命名为a
a.x=2
a.printf()
a.__name = 3 # 不能直接访问私有属性,新建了一个属性
a.printf()