python知识:装饰器@property到底有啥用途

作者:无水先生 时间:2022-07-23 12:25:45 

一、提要

python的@property是python的一种装饰器,是用来修饰方法的。

python @property 装饰器使一个方法可以像属性一样被使用。

除此之外,还有几个使用场景,本文将叙述这些使用技巧。

二、关于属性的约定

首先看下属性的分类:

2.1 类绑定属性

一般类内属性是指定义成与类同一存储单元的属性,可以类访问。

而当类实例化成对象后,类变量将做为拷贝加入对象,对象所访问的属性是一份拷贝。

这份拷贝修改后易变。

python知识:装饰器@property到底有啥用途

验证代码

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,装饰器,@property
0
投稿

猜你喜欢

  • macOS安装Solr并索引MySQL

    2024-01-17 13:57:08
  • PHP模板引擎Smarty的缓存使用总结

    2023-11-15 09:55:12
  • Python中设置变量作为默认值时容易遇到的错误

    2023-09-14 09:32:00
  • 打造设计你自己的字体 Ⅱ

    2008-03-14 07:48:00
  • python里将list中元素依次向前移动一位

    2021-03-23 16:53:43
  • 跟老齐学Python之变量和参数

    2023-01-12 22:23:31
  • Python3.7 基于 pycryptodome 的AES加密解密、RSA加密解密、加签验签

    2022-12-10 13:55:18
  • Python实现的对一个数进行因式分解操作示例

    2023-01-11 04:30:40
  • php遍历CSV类实例

    2023-11-01 23:46:26
  • 解决IIS出现Active Server Pages错误“ASP 0201”

    2009-05-25 18:04:00
  • MySQL数据库操作DQL正则表达式

    2024-01-14 13:04:48
  • python利用小波分析进行特征提取的实例

    2023-01-02 01:02:22
  • asp获取文件md5值

    2008-10-13 09:10:00
  • 使用tensorflow DataSet实现高效加载变长文本输入

    2022-12-09 09:26:09
  • Vscode编辑器的巧妙用法(快速格式化代码的方法)

    2022-07-02 01:13:33
  • 浅谈用户注册表单

    2008-11-13 12:27:00
  • JavaScript简介

    2024-04-10 10:43:17
  • 通过分析SQL语句的执行计划优化SQL

    2011-10-24 20:03:20
  • 推荐五个常用的python图像处理库

    2022-07-20 10:40:38
  • 常用原生js自定义函数总结

    2024-04-16 09:05:57
  • asp之家 网络编程 m.aspxhome.com