@property装饰器

-- TOC --

python对象本质上是没有私有成员的,用双下划线的方式定义的成员,也可以通过附加类名的方式来访问。不过,这种奇怪的访问方式在编写代码的时候,应该是要被禁止的。

使用一个下划线来暗示这是私有成员,也是一种方法,不过没有强制力,修改的时候,也没有任何约束力。python提供了一个@property装饰器,可以更好的控制对象成员的访问和修改。

下面的代码示例,用@property修饰一个成员函数,将其变成一个成员变量来访问:

class test():
    def __init__(self):
        self.__foo = 'foo'
        self.__bar = 'bar'

    @property
    def foo(self):
        # print('running in foo function')
        return self.__foo


t = test()
print(t.foo)

用@property装饰的foo函数,就变成了foo成员变量,访问这个成员变量的时候,触发内部的一个函数执行。此时,foo这个成员变量只能读,不能写,如果尝试使用t.foo=123来赋值,会出现错误:AttributeError: can't set attribute。

下面的代码示例,实现修改内部__foo成员的功能:

class test():
    def __init__(self):
        self.__foo = 'foo'
        self.__bar = 'bar'

    @property
    def foo(self):
        # print('running in foo function')
        return self.__foo

    @foo.setter
    def foo(self, foo_value):
        if foo_value < 100: 
            pass
        else:
            self.__foo = foo_value

t = test()
print(t.foo)
t.foo = 123
print(t.foo)

注意@foo.setter这个装饰器的由来。在设置的时候,外部代码还是简简单单地使用等号实现,而触发的是内部的一段代码,这段代码可以实现设置前的检查!

下面的代码,实现对某个成员的删除控制:

class test():
    def __init__(self):
        self.__foo = 'foo'
        self.__bar = 'bar'

    @property
    def foo(self):
        # print('running in foo function')
        return self.__foo

    @foo.setter
    def foo(self, foo_value):
        if foo_value < 100: 
            pass
        else:
            self.__foo = foo_value

    @foo.deleter
    def foo(self):
        if self.__foo > 200:
            self.__foo = 200

t = test()
print(t.foo)
t.foo = 123
print(t.foo)
t.foo = 234
print(t.foo)
del t.foo
print(t.foo)

注意@foo.deleter这个装饰器。

执行del t.foo语句的时候,同样触发一段自定义代码,上面的代码示例,并没有真正删除foo这个变量,只是限制它的值。

被@foo.setter和被@foo.deleter装饰的成员函数名称,都必须是foo。

通过@property装饰器,以及其衍生出来的一些其它装饰器,我们可以通过简单的语义实现复杂的功能,可以增加代码的可读性。

@property装饰后的属性,可以被继承

class aaa():
    def __init__(self):
        self.a = 1

    @property
    def geta(self):
        return self.a

    @geta.setter
    def geta(self, value):
        self.a = value


class bbb(aaa):
    pass


ina = aaa()
print(ina.geta)
ina.geta = 2
print(ina.geta)

inb = bbb()
print(inb.geta)
inb.geta = 3
print(inb.geta)

可以被继承这一点,我以前不是特别理解,现在已经理解,并且觉得都不需要在笔记中写出来。

本文链接:https://cs.pynote.net/sf/python/202203211/

-- EOF --

-- MORE --