关键词

python中的property及属性与特性之间的优先权

Python中的property是一种特殊的装饰器,它可以将函数转换为属性,即方法调用像属性一样使用。在Python中,属性和特性是一对密切相关的概念,因为它们共同构成了一个类的接口。

一、property的使用

1.1 基本用法

假设现在有一个名为Person的类,有属性name和age,我们需要对属性进行一些限制。下面是使用property实现对属性访问的过程:

class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age

    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if not isinstance(value, int):
            raise ValueError("age must be an integer")
        if value <= 0 or value > 120:
            raise ValueError("age must between 1 and 120")
        self._age = value

p = Person("Bob", 20)
print(p.name)  # output: Bob
print(p.age)  # output: 20
p.age = 25  # set age
print(p.age)  # output: 25

在上面的示例中,我们通过@property将name和age方法转换为属性。对于getter方法,我们直接使用@property进行装饰;对于setter方法,我们需要使用@xxx.setter装饰器,其中xxx表示属性名。

1.2 高级用法

除了基本用法之外,property还有一些高级用法,比如可以使用property实现只读属性,如果尝试设置只读属性,就会引发AttributeError异常。示例代码如下所示:

class Person:
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

    @property
    def age(self):
        raise AttributeError("age is a read-only attribute")

p = Person("Bob")
print(p.name)  # output: Bob
print(p.age)  # output: AttributeError
p.age = 25  # set age, AttributeError

二、属性和特性之间的优先权

Python中的属性和特性之间存在着优先权,即如果类中既有属性又有特性,那么Python会根据以下规则来决定调用哪个:

  1. 如果属性的名字与特性的名字相同,那么属性拥有优先权,Python将访问该属性,而不是访问特性。
  2. 如果通过属性访问特性,那么特性也就拥有了优先权。
  3. 如果特性具有setter方法,那么通过属性访问特性是相当于调用该setter方法,即该特性也就成为属性成分的一部分,因此其优先权也是较高的。

以下是示例代码,用来说明属性和特性之间的优先权:

class DemoClass:
    def __init__(self):
        self._value = 1

    @property
    def value(self):
        print("get value")
        return self._value

    @value.setter
    def value(self, v):
        print("set value=%s" % v)
        self._value = v

    def __getattr__(self, name):
        print("__getattr__ %s" % name)
        return "not found"

    def __getattribute__(self, name):
        print("__getattribute__ %s" % name)
        return object.__getattribute__(self, name)

d = DemoClass()
print(d.value)  # output: __getattribute__ value\nget value\n1
print(d.__dict__)  # output: {'_value': 1}
d.value = 2  # output: __getattribute__ value\nset value=2
print(d.__dict__)  # output: {'_value': 2}
print(d.x)  # output: __getattribute__ x\n__getattr__ x\nnot found

从上面的示例可以看出,通过属性访问特性时,特性具有更高的优先权。此外,如果属性和特性的名字相同,则属性拥有更高的优先权。如果属性和特性都不存在,那么Python将调用对象的__getattr__方法。此外,属性和方法的优先级同样存在关系,如果属性和方法的名字相同,那么属性拥有更高的优先级。

本文链接:http://task.lmcjl.com/news/14730.html

展开阅读全文