python装饰器 property_Python中的内置装饰器之property

装饰器是Python中很重要的一个概念,但是这篇文档不介绍装饰器的实现,我们只需要知道装饰器可以实现一些功能;

Python中也包含一些自带的装饰器,这次就说一下属性装饰器property

相关知识点

用法

property装饰器的作用是让一个类方法的访问方式变成属性的访问方式,用法如下:

class Num:

@property

def x(self):

return '用类方法定义,用property装饰的x'

a = Num() # 把C实例化,命名为a

print(a.x) # 我们访问了a实例的x方法,但是没有对x做调用,和访问实例属性的方法一样

输出:用类方法定义,用property装饰的x

作用

使用这种方式来定义实例属性,我们就可以在类属性x中对x做一定的校验,这一点我们在后面再说。

衍生装饰器

举一个数字相加的例子:

class Num:

@property

def x(self):

return 1

@property

def y(self):

return 2

def printf(self):

print(f'{self.x}加{self.y}的和是:{self.x+self.y}')

a = Num() # 把C实例化,命名为a

a.printf()

这个例子和上面的例子一样,我们定义了属性x和y,输出了x+y的和

这个例子的输出是:1加2的和是:3

这个时候我们希望可以在外部修改x的值,就会发现无法修改,因为本质上x是一个方法,而不是类属性:

class Num:

@property

def x(self):

return 1

@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

print(a.x)

输出:AttributeError: can't set attribute

所以我们需要另外在类中定义一个方法,来修改x的值,相当于给外部创建一个API接口,让外部通过这个API来修改,这就用到了setter装饰器:

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

输出:2加2的和是:4

这样我们就可以通过a.x = 2来给self.num重新赋值,这样做的好处是不改变外层修改x值的方式,来实现对property属性的修改,这也是让代码更高可用,更可读很重要的一点。

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)

输出:

2加2的和是:4

AttributeError: 'Num' object has no attribute 'num'

deleter装饰器装饰的方法就可以被使用del 来删除对应的属性,删除属性的操作我们就再同名方法x中进行了实现,

这样外部删除属性的方法也和删除一个属性的方法保持一致,同样保证了高可用性和可读性。

作用

现在可以说明文章一开始说的作用了,

我们通过这种property,setter,deleter装饰器的方式,把实例属性self.num写成property属性,我们就可以完成一个操作,

对外部修改、删除属性的操作,做进一步的过滤和限制

还是同样的例子,我们希望可以限制上层代码实例化并且修改x的值为非int类型,因为这会造成我们的求和方法报错,我们就可以通过这种方式实现:

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!!!')

@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 = '1234567' # 突发奇想把x的值改为str类型

输出:不要把非int类型赋值给x!!!

综上,这样就可以保障上层在修改x的值的时候,可以被我们的同名装饰器x先做进一步校验,

当然你想要先对入参item做一些其他操作也一样可以,操作之后,再更改self.num为item,

这个时候printf 求和方法,就可以安全使用 + 运算符求和了。

总结

使用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.__name = 3 # 修改私有属性为3

a.printf()

这样外部就不能通过 a.__name = 3的方式来改变私有属性__name,如果需要修改,就要通过a.x = 3的“API”来修改,从而我们可以对“API入参”进行校验和处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值