Python中有一个被称为属性函数(property)的小概念,它可以做一些有用的事情。在这篇文章中,我们将看到如何能做以下几点:

  • 将类方法转换为只读属性
  • 重新实现一个属性的setter和getter方法

一、装饰器

使用属性函数的最简单的方法之一是将它作为一个方法的装饰器来使用。这可以让你将一个类方法转变成一个类属性。当我需要做某些值的合并时,我发现这很有用。其他想要获取它作为方法使用的人,发现在写转换函数时它很有用。让我们来看一个简单的例子:

class Person(object):
"""""" #----------------------------------------------------------------------
def __init__(self, first_name, last_name):
"""Constructor"""
self.first_name = first_name
self.last_name = last_name #----------------------------------------------------------------------
@property
def full_name(self):
"""
Return the full name
"""
return "%s %s" % (self.first_name, self.last_name)

在上面的代码中,我们创建了两个类属性:self.first_nameself.last_name。接下来,我们创建了一个full_name方法,它有一个@property装饰器。这使我们能够在Python解释器会话中有如下的交互:

>>> person = Person("Mike", "Driscoll")
>>> person.full_name
'Mike Driscoll'
>>> person.first_name
'Mike'
>>> person.full_name = "Jackalope"
Traceback (most recent call last):
File "<string>", line 1, in <fragment>
AttributeError: can't set attribute

正如你所看到的,因为我们将方法变成了属性,我们可以使用正常的点符号访问它。但是,如果我们试图将该属性设为其他值,我们会引发一个AttributeError错误。改变full_name属性的唯一方法是间接这样做:

>>> person.first_name = "Dan"
>>> person.full_name
'Dan Driscoll'

二、使用python property 替代 setter 和 getter 方法

让我们假设我们有一些遗留代码,它们是由一些对Python理解得不够好的人写的。如果你像我一样,你之前已经看到过这类的代码:

from decimal import Decimal

########################################################################
class Fees(object):
"""""" #----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
self._fee = None #----------------------------------------------------------------------
def get_fee(self):
"""
Return the current fee
"""
return self._fee #----------------------------------------------------------------------
def set_fee(self, value):
"""
Set the fee
"""
if isinstance(value, str):
self._fee = Decimal(value)
elif isinstance(value, Decimal):
self._fee = value

要使用这个类,我们必须要使用定义的getter和setter方法​​:

>>> f = Fees()
>>> f.set_fee("")
>>> f.get_fee()
Decimal('')

如果你想添加可以使用正常点符号访问的属性,而不破坏所有依赖于这段代码的应用程序,你可以通过添加一个属性函数非常简单地改变它:

from decimal import Decimal

########################################################################
class Fees(object):
"""""" #----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
self._fee = None #----------------------------------------------------------------------
def get_fee(self):
"""
Return the current fee
"""
return self._fee #----------------------------------------------------------------------
def set_fee(self, value):
"""
Set the fee
"""
if isinstance(value, str):
self._fee = Decimal(value)
elif isinstance(value, Decimal):
self._fee = value fee = property(get_fee, set_fee)

我们在这段代码的末尾添加了一行。现在我们可以这样做:

>>> f = Fees()
>>> f.set_fee("")
>>> f.fee
Decimal('')
>>> f.fee = ""
>>> f.get_fee()
Decimal('')

正如你所看到的,当我们以这种方式使用属性函数时,它允许fee属性设置并获取值本身而不破坏原有代码。让我们使用属性装饰器来重写这段代码,看看我们是否能得到一个允许设置的属性值。

from decimal import Decimal

########################################################################
class Fees(object):
"""""" #----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
self._fee = None #----------------------------------------------------------------------
@property
def fee(self):
"""
The fee property - the getter
"""
return self._fee #----------------------------------------------------------------------
@fee.setter
def fee(self, value):
"""
The setter of the fee property
"""
if isinstance(value, str):
self._fee = Decimal(value)
elif isinstance(value, Decimal):
self._fee = value #----------------------------------------------------------------------
if __name__ == "__main__":
f = Fees()

上面的代码演示了如何为fee属性创建一个setter方法。你可以用一个名为@fee.setter的装饰器装饰第二个方法名也为fee的方法来实现这个。当你如下所做时,setter被调用:

>>> f = Fees()
>>> f.fee = ""

如果你看属性函数的说明,它有fget, fset, fdel和doc几个参数。如果你想对属性使用del命令,你可以使用@fee.deleter创建另一个装饰器来装饰相同名字的函数从而实现删除的同样效果。

三、property函数

property() 函数的作用是在新式类中返回属性值。

class property([fget[, fset[, fdel[, doc]]]])
# fget -- 获取属性值的函数
# fset -- 设置属性值的函数
# fdel -- 删除属性值函数
# doc -- 属性描述信息
class C(object):
def __init__(self):
self._x = None def getx(self):
return self._x def setx(self, value):
self._x = value def delx(self):
del self._x x = property(getx, setx, delx, "I'm the 'x' property.")

如果 c 是 C 的实例化,

c.x                将触发 getter,

c.x = value   将触发 setter ,

del c.x          触发 deleter。

如果给定 doc 参数,其将成为这个属性值的 docstring,否则 property 函数就会复制 fget 函数的 docstring(如果有的话)。

python - property 属性函数的更多相关文章

  1. Python——@property属性描述符

    @property 可以将python定义的函数“当做”属性访问,从而提供更加友好访问方式,但是有时候setter/getter也是需要的 假设定义了一个类Cls,该类必须继承自object类,有一私 ...

  2. python @property 属性

    在绑定属性时,如果我们直接把属性暴露出去,显然不合适,是通过getter和setter方法来实现的,还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性: class P ...

  3. python property属性

    能够检查參数,一直没注意这个语言特性,忽略了非常多细节,感谢 vitrox class Person( object ): def __init__( self, name ): if not isi ...

  4. (转)Python内置函数进阶之“属性(property())”详解

    原文:https://blog.csdn.net/GeekLeee/article/details/78519767 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.c ...

  5. 网络编程-Python高级语法-property属性

    知识点: 一.什么是property属性? 一种用起来像是使用的实例属性一样的特殊属性,可以对应于某个方法,Python的property属性的功能是:property属性内部进行一系列的逻辑计算,最 ...

  6. Python property() 函数

    Python property() 函数  Python 内置函数 描述 property() 函数的作用是在新式类中返回属性值. 语法 以下是 property() 方法的语法: class pro ...

  7. Python学习手册之数据封装、类方法、静态方法和属性函数

    在上一篇文章中,我们介绍了 Python 的内部方法.操作符重载和对象生命周期,现在我们介绍 Python 的数据封装.类方法.静态方法和属性函数.查看上一篇文章请点击:https://www.cnb ...

  8. Python内置函数之-property

    property 是一个内置的装饰器函数,只在面向对象中使用 求一个圆的周长和面积 # 周长和面积都是通过类的方法得到from math import pi class Cricle: def __i ...

  9. python中的property属性

    目录 1. 什么是property属性 2. 简单的实例 3. property属性的有两种方式 3.1 装饰器方式 3.2 类属性方式,创建值为property对象的类属性 4. property属 ...

随机推荐

  1. 上载和下载CSV文件

    sap中把txt .excel .文件上载到内表中,txt和csv速度最快. excel文件导出的csv是用,分隔符分隔的,如果单元格的文本中就有逗号,这样会和分隔符逗号混淆,最好abap产生csv文 ...

  2. lua基础(2)

    错误处理: local function add(a,b) assert(type(a) == "number", "a 不是一个数字") assert(typ ...

  3. Spring Framework Part3 IoC and Dynamic Proxy

    spring serious of blog edit by 马士兵教育 Maven方式创建Spring工程 工程创建 1.新建项目 选择Maven Project 2.勾选 Create a sim ...

  4. 牛客假日团队赛5 L Catch That Cow HDU 2717 (BFS)

    链接:https://ac.nowcoder.com/acm/contest/984/L 来源:牛客网 Catch That Cow 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 3 ...

  5. Connection refused 排查过程

    Connection refused 排查过程 connection refused  排查  起因 今天在连接 rabbitmq 时,报 Connection refused (如下图),借此机会记 ...

  6. npm 全局安装和局部安装的区别

    上图是从网上找的webpack 安装的步骤,我们看到除了要全局安装之外,还需要本地安装,那么这两者有什么区别呢? 本文以Windows平台上做测试,以webpack为示例做教程 什么是全局安装? 安装 ...

  7. 网络吞吐量(network)

    题目 分析 过一遍spfa,把从点1到其他每一个点的最短路求出来, 接着递归把所有最短路径上的路径保留,其他的删掉. 对于保留的路径作为网络流的边,流量为无穷大,对于每个点拆点两个点之间的流量为吞吐量 ...

  8. Node.js之querystring模块

    querystring从字面上的意思就是查询字符串,一般是对http请求所带的数据进行解析.querystring模块只提供4个方法,在我看来,这4个方法是相对应的. 这4个方法分别是querystr ...

  9. The Preliminary Contest for ICPC Asia Shanghai 2019 D. Counting Sequences I

    题目:https://nanti.jisuanke.com/t/41412思路:dfs           先取ai>2  2^12>3000 因此至多取11个 其余用1补        ...

  10. MFC多文档获取窗口句柄

    GET App   AfxGetInstanceHandle()    AfxGetApp()   GET Frame->View->Document     SDI    AfxGetM ...