python知识:装饰器@property到底有啥用途
作者:无水先生 发布时间:2022-07-23 12:25:45
一、提要
python的@property是python的一种装饰器,是用来修饰方法的。
python @property 装饰器使一个方法可以像属性一样被使用。
除此之外,还有几个使用场景,本文将叙述这些使用技巧。
二、关于属性的约定
首先看下属性的分类:
2.1 类绑定属性
一般类内属性是指定义成与类同一存储单元的属性,可以类访问。
而当类实例化成对象后,类变量将做为拷贝加入对象,对象所访问的属性是一份拷贝。
这份拷贝修改后易变。
验证代码
class Stranger(object):
name = 'class name' #类绑定属性
def __init__(self, gender=None ):
self.gender = gender #对象绑定属性
self.name = 'new name' #对象中属性,与类属性的同名拷贝
stan = Stranger('male')
print(1,stan.gender)
stan.gender = 'famel'
print(2,stan.gender)
print(3 stan.name)
print( 4, Stranger.name)
结果:
1 male
2 famel
3 new name
4 class name
2.2 对象绑定属性
凡用self定义的属性,都是对象绑定属性,
内部调用时都需要加上self.
外部调用时用 instance_name.property_name进行访问
class Stranger(object):
def __init__(self, gender=None ):
self.gender = gender
stan = Stranger('roma')
print(stan.gender)
stan.gender = 'Paras'
print(stan.gender)
结果:
roma
Paras
注意:事实上实例化后的对象,也可以定义属性,外部也可以调用。
2.3 私有属性
python的私有属性没有编译限定,知识以单下划线_开头,标记此属性是私有的,但是外部也可以自由访问(私有的程度不够多)。
另一种是双下划线__开头的属性,可以转化成类属性访问
单下划线_开头:只是告诉别人这是私有属性,外部依然可以访问更改
双下划线__开头:外部不可通过instancename.propertyname来访问或者更改,实际将其转化为了_classname__propertyname
三、应用@property装饰器
python的@property是python的一种装饰器,是用来修饰方法的。python @property 装饰器使一个方法可以像属性一样被使用,而不需要在调用的时候带上()
接下来我们会了解什么时候需要使用它,并且在什么场景下需要用到它以及如何合理的使用它。
python类中@property装饰器,相配合的方法有:
setter()
get()
set()
相配合。
3.1 将一个属性转成方法
将一个属性转化为一个方法时,我们最好加上一个@property
装饰器来解决这个问题。
在方法定义上面加一个@property
装饰器,可以在不改变原有调用方式的同时,来将一个属性改为一个方法。
class Goods():
def __init__(self,unit_price,weight):
self.unit_price = unit_price
self.weight = weight
@property
def price(self):
return self.unit_price * self.weight
lemons = Goods(7,4)
print(lemons.price)
28
上文中,price是方法,现在将方法转化成属性调用。注意这个技巧,要知道原类定义中无price这个属性,这是一个临时产生的结果。类同于excel表格的“计算项”。
3.2 私有化某些属性
对于某些属性,不可直接访问。这里的“直接”就是“无条件”的意思;而条件的访问,就需要装饰器 @property,下例是双装饰器@property和@age.setter配合,对_age进行条件隔离的例子:
class Stranger(object):
def __init__(self, gender=None, age=None, job=None):
self.gender = gender
self._age = age # 这里的成员属性_age需要与成员方法age()区分开
self.jobb = job
# 读取age
@property # 实现一个age相关的getter方法
def age(self):
return self._age
# 设置age
@age.setter # 实现一个age相关的setter方法
def age(self, value):
if isinstance(value, int):
self._age = value
else:
raise ValueError("'int' type need")
if __name__ == "__main__":
# 创建一个“妹子”
meizi = Stranger()
meizi.age = 18 # 使用时注意是.age,不是._age
print("年龄:{age}".format(age=meizi.age))
注意事项:
属性名与方法名一定要区分开,不然会进入死循环(self._age,def age())
实例化的对象使用属性时,不是调用属性(meizi._age),而是用的方法名(meizi.age)
@property其实就是实现了getter功能; @xxx.setter实现的是setter功能;还有一个 @xxx.deleter实现删除功能
定义方法的时候 @property必须在 @xxx.setter之前,且二者修饰的方法名相同(age())
如果只实现了 @property(而没有实现@xxx.setter),那么该属性为 只读属性
3.3 关联性修改
比如,我们输入了first_name、last_name可以得出fullname,下面代码可以实现全名的属性获取。而反过来,对全名进行修改后,如何将连带的first_name、last_name同步进行修改?。
下文中的 @fullname.setter就是解决此类问题的。
class Person():
def __init__(self, first_name, last_name):
self.first = first_name
self.last = last_name
@property
def fullname(self):
return self.first + ' ' + self.last
@fullname.setter
def fullname(self, name):
first_name, last_name = name.split()
self.first = first_name
self.last = last_name
def email(self):
return '{}.{}@email.com'.format(self.first, self.last)
person = Person('zhang', 'san')
print(person.fullname)
print(person.last)
print(person.first)
person.fullname = 'li si'
print(person.fullname)
print(person.last)
print(person.first)
3.4 删除属性的deleter方法
和setter
方法类似,当我们需要删除一个属性时,我们会使用deleter
方法。
你可以像定义setter
方法一样来定义一个setter
方法,使用相同的方法名,并在方法上添加@{methodname}.deleter
装饰器 。
class Person():
def __init__(self, first_name, last_name):
self.first = first_name
self.last = last_name
@property
def fullname(self):
return self.first + ' ' + self.last
@fullname.setter
def fullname(self, name):
first_name, last_name = name.split()
self.first = first_name
self.last = last_name
@fullname.deleter
def fullname(self):
self.first = None
self.last = None
def email(self):
return '{}.{}@email.com'.format(self.first, self.last)
person = Person('zhang', 'san')
print(person.fullname)
print(person.last)
print(person.first)
del person.fullname
print(person.last)
print(person.first)
四、property()函数原理
使用该函数可以将方法直接变成属性,与@property类同。
函数接口:
property(fget=None, fset=None, fdel=None, doc=None)
使用property的代码示例:
class Stranger(object):
def __init__(self, gender=None, age=None, job=None):
self.gender = gender
self._age = age
self.jobb = job
# 设置_age
def set_age(self, age):
if isinstance(age, int):
self._age = age
else:
raise ValueError("'int' type need")
# 读取_age
def get_age(self):
return self._age
# 使得实例化对象可以利用.age方式来访问
age = property(get_age, set_age)
if __name__ == "__main__":
# 创建一个“妹子”
meizi = Stranger()
meizi.age = 18
print("年龄:{age}".format(age=meizi.age))
# 输出:
#年龄:18
来源:https://yamagota.blog.csdn.net/article/details/125402452


猜你喜欢
- 本文实例讲述了Python输出PowerPoint(ppt)文件中全部文字信息的方法。分享给大家供大家参考。具体分析如下:下面的代码依赖于w
- 使用php,定义php的默认语言. php.ini中: default_charset = "gb2312" 在网页中输
- 今日上课,有位同学问到:w和w+有何区别呢。说实话,我们经常只是用一种权限,没用在意之间的区别,实际上,w+具有可读可写权限,而w只有可写权
- 本文以实例形式实现了python监控linux性能以及进程消耗性能的方法,具体实现代码如下:# -*- coding: utf-8 -*-&
- 之前很多次用到的时候总会忘一些,这次记下来,后面再忘了就直接来这查~。string转其它string --> int:将字符串13转换
- python使用matplotlib的savefig保存时图片保存不完整的问题使用如下形式的代码进行图片保存时,保存的图片出现不完整的情况,
- 前言虽然各种编程语言之间大部分语法存在共通的地方,但是在一些细节的处理上还是千差万别才接触Python不久(之前是学Java的),实在想吐槽
- 当鼠标移动上去后,字慢慢的变大的 效果应该 如果实现啊<!DOCTYPE html PUBLIC "-//W3C//DTD
- 最近有点审美疲劳,以往看起来觉得漂亮的界面现在觉得很一般,以前觉得看来还行的界面现在觉得很丑了。想来是时候休息一下了。唯美觉得上次做的OA登
- 微信小程序 scroll-view实现上拉加载与下拉刷新的实例实现效果图:如图,使用小程序的scroll-view实现的上拉加载数据,下拉刷
- Python实现模拟时钟代码推荐# coding=utf8import sys, pygame, math, randomfrom pyga
- Windows客户端业务群产品营销主管斯蒂芬最近在向记者示范Internet Explorer 8 Beta2版浏览器的技术特征时标识,与用
- 今天给大家分享一个简单的python脚本,使用python进行http的接口测试,脚本很简单,逻辑是:读取excel写好的测试用例,然后根据
- 微服务架构在现代软件开发中日益普及,它将复杂的应用程序拆分成多个可独立部署的小型服务。本文将介绍如何使用 Python 的 FastAPI
- 前言最近完整地看了一遍TypeScript的官方文档,发现文档中有一些知识点没有专门讲解到,或者是讲解了但却十分难以理解,因此就有了这一系列
- python运行问题Traceback (most recent call last)出现报错traceback(most recent c
- 1.消息丢失1.生产者发送失败所有消息队列都可能发生的问题生产者发送消息后,队列未成功接收(网络原因或其他)而生产者不知情,消息丢失生产者发
- 在python中,可以把for循环写在一行,生成一个新的列表,使用起来非常方便,下面举几个简单例子体会一下。1.简单的for...[if].
- 工具python3.7PycharmExcelpython-docx生成Word案例创建一个demo.doc文档,代码如下:from doc
- 前言千位分隔符,其实就是数字中的逗号。依西方的习惯,人们在数字中加进一个符号,以免因数字位数太多而难以看出它的值。所以人们在数字中,每隔三位