【python进阶】property函数

文章目录

    • 原型
    • 只读属性
    • 更多

原型

class property(fget=None, fset=None, fdel=None, doc=None)

它返回的是一个属性。

比如:

class C:
    @property
    def x(self):
        return None

    print(type(x))

可以看见打印的结果是:

<class 'property'>

也就是说返回的x其实是一个类对象,记住,不是类的实例,它本身就是一个类,叫property。这个类有setter和deleter两个方法,下面会用到。

也就是说property其实是一个类,在初始化的时候,可以给定上面的4个参数,前面三个参数,都是接收函数类型的参数,分别用于获取属性的值,设置属性的值,和删除属性,最后一个doc用于设定属性的docstring。

看一下它和类属性的区别:

class C:
    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.")
    y = 1

c = C()
print(C.x)
print(C.y)
print(c.x)
print(c.y)

打印的结果是:

<property object at 0x000002789820F458>
1
None
1

也就是说其实x也是一个类属性,只不过,如果通过了C的实例c去访问,就会访问到对应的getx setx delx等方法上。

我们看一个实例:

class C:
    def __init__(self):
        self._x = None

    def getx(self):
        print('getter')
        return self._x

    def setx(self, value):
        print('setter')
        self._x = value

    def delx(self):
        print('deleter')
        del self._x

    x = property(getx, setx, delx, "I'm the 'x' property.")


c = C()
print(c.x)
c.x = 1
print(c.x)
del c.x
# print(c.x) #由于上面使用del,所以这里会报错

最后的打印结果是:

getter
None
setter
getter
1
deleter

其实很类似下面的MyProperty(如果你熟悉描述器的概念,下面的很好理解):

class MyProperty:
    def __init__(self, getter, setter, deleter, docstr):
        self.getter = getter
        self.setter = setter
        self.deleter = deleter
        self.docstr = docstr

    def __get__(self, instance, owner):
        return self.getter(instance)

    def __set__(self, instance, value):
        self.setter(instance, value)


class C:
    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 = MyProperty(getx, setx, delx, "I'm the 'x' property.")


c = C()
print(c.x)
c.x = 1
print(c.x)

只读属性

如果我们想让某个属性只能可读,不能被修改,那么可以使用下面的方式:

class C:
    def __init__(self):
        self._x = 1

    @property
    def x(self):
        return self._x


c = C()
print(c.x)
# c.x = 1 # 因为设置为了只读属性,这里修改会报错

最后的结果是:

1

类似,我们也可以编写一个替换(当然,本文的很多替换,由于是举例,并没有考虑所有情况,只会对当前用到的情况进行代码的编写):

class MyProperty:
    def __init__(self, getter=None, setter=None, deleter=None, docstr=None):
        self.getter = getter
        self.setter = setter
        self.deleter = deleter
        self.docstr = docstr

    def __get__(self, instance, owner):
        return self.getter(instance)

    def __set__(self, instance, value):
        if not self.setter:
            raise AttributeError("can't set attribute")


class C:
    def __init__(self):
        self._x = 1

    @MyProperty
    def x(self):
        return self._x


c = C()
print(c.x)
c.x = 1

结果:

1

最后抛出AttributeError: can't set attribute异常。

更多

按照上面的使用@property的方式后,属性变成只读的了,如果要变成可写可删除,那么可以使用下面的方式:

class C:
    def __init__(self):
        self._x = 1

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x


c = C()
print(c.x)
c.x = 2
print(c.x)
del c.x
# print(c.x) # 这里抛出异常

结果:

1
2

你可能感兴趣的:(【python进阶】property函数)