python3 -属性(property)

简介: Python中有一个被称为属性函数(property)的小概念,它可以做一些有用的事情。在这篇文章中,我们将看到如何能做以下几点:将类方法转换为只读属性重新实现一个属性的setter和...

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)

person = Person("Mike", "Driscoll")
print(person.full_name)
print(person.first_name)

#Mike Driscoll
#Mike

# person.full_name = "Jackalope"  # AttributeError: can't set attribute

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

person.first_name = "Dan"
print(person.full_name) #Dan Driscoll

使用Python property取代setter和getter方法

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

f = Fees()
f.set_fee("1")
print(f.get_fee())  # 1

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

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("1")
print(f.fee)  # 1

f.fee = "2"
print(f.get_fee())  # 2

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

把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值

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()
    f.fee = '10'
    print(f.fee)    # 10

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

class Person:
    def __init__(self,first_name):
        self.first_name = first_name

    # Getter function
    @property
    def first_name(self):
        return self._first_name

    # Setter function
    @first_name.setter
    def first_name(self,value):
        if not isinstance(value, str):
            raise TypeError('Expected a string')
        self._first_name = value

    # Deleter function (optional)
    @first_name.deleter
    def first_name(self):
        raise AttributeError("Can't delete attribute")


if __name__ == '__main__':
    a = Person('Guido')
    print(vars(a))
    # print(a.first_name)     # Guido
    # a.first_name = 42   # Calls the setter
#   outputs: TypeError: Expected a string

在实现一个property的时候,底层数据(如果有的话)仍然需要存储在某个地方。 因此,在get和set方法中,你会看到对 _first_name 属性的操作,这也是实际数据保存的地方。 另外,你可能还会问为什么 init() 方法中设置了 self.first_name 而不是 self._first_name 。 在这个例子中,我们创建一个property的目的就是在设置attribute的时候进行检查。 因此,你可能想在初始化的时候也进行这种类型检查。通过设置 self.first_name ,自动调用 setter 方法, 这个方法里面会进行参数的检查,否则就是直接访问 self._first_name 了。

目录
相关文章
|
6月前
|
Python
解决Python报错:DataFrame对象没有concat属性的多种方法(解决方案汇总)
总的来说,解决“DataFrame对象没有concat属性”的错误的关键是理解concat函数应该如何正确使用,以及Pandas库提供了哪些其他的数据连接方法。希望这些方法能帮助你解决问题。记住,编程就像是解谜游戏,每一个错误都是一个谜题,解决它们需要耐心和细心。
281 15
|
9月前
|
物联网 Python
请问:如何使用python对物联网平台上设备的属性进行更改?
为验证项目可行性,本实验利用阿里云物联网平台创建设备并定义电流、电压两个整型属性。通过Python与平台交互,实现对设备属性的控制,确保后续项目的顺利进行。此过程涵盖设备连接、数据传输及属性调控等功能。
|
8月前
|
C语言 Python
Python学习:内建属性、内建函数的教程
本文介绍了Python中的内建属性和内建函数。内建属性包括`__init__`、`__new__`、`__class__`等,通过`dir()`函数可以查看类的所有内建属性。内建函数如`range`、`map`、`filter`、`reduce`和`sorted`等,分别用于生成序列、映射操作、过滤操作、累积计算和排序。其中,`reduce`在Python 3中需从`functools`模块导入。示例代码展示了这些特性和函数的具体用法及注意事项。
108 2
|
缓存 Java Python
python-静态方法staticmethod、类方法classmethod、属性方法property_python staticmethod类内使用(1)
python-静态方法staticmethod、类方法classmethod、属性方法property_python staticmethod类内使用(1)
|
10月前
|
存储 数据处理 Python
Python如何显示对象的某个属性的所有值
本文介绍了如何在Python中使用`getattr`和`hasattr`函数来访问和检查对象的属性。通过这些工具,可以轻松遍历对象列表并提取特定属性的所有值,适用于数据处理和分析任务。示例包括获取对象列表中所有书籍的作者和检查动物对象的名称属性。
203 2
|
12月前
|
索引 Python
python-类属性操作
【10月更文挑战第11天】 python类属性操作列举
106 1
|
程序员 开发者 Python
Python动态属性与反射机制方式
通过反射和动态属性,Python程序员获得了巨大的权能,能在运行时访问、修改或为对象新增属性和方法,显著提高编程的智能化和适应性。内置的反射机制可能使开发者跨越编写代码时的限制,通过名称访问对象的特性、方法以及其他成员,为创建一个具有高度配置性、扩展性强大的应用程序打下基础。此外,利用getattr和setattr函数来获取和设定对象的属性,或是利用hasattr确认其是否存在某属性,甚至可以通过名字来动态地执行对象的函数。 总之,反射和动态属性对于Python的程序开发而言是重要的工具,它们不仅提供了编写效率高且灵活的代码的能力,还为构建可高度定制和扩展的应用程序提供了可能。对于熟练掌握这些
|
存储 API 索引
让 Python 的属性查找具有 C 一级的性能
让 Python 的属性查找具有 C 一级的性能
62 0
|
Python
Python中类属性与实例属性的区别
了解这些区别对于编写高效、易维护的Python代码至关重要。正确地使用类属性和实例属性不仅能帮助我们更好地组织代码,还能提高代码运行的效率。
234 0
Python类中属性和方法区分3-8
Python类中属性和方法区分3-8

推荐镜像

更多