构造多方法设置器的pythonic方法

时间:2019-06-28 11:03:52

标签: python python-3.x class getter-setter

我们可以使用@property来构造一个getter和setter方法。这是一个简短的示例,我们如何做到这一点:

class A:

    def __init__(self,x):
        self.x = x

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

    @x.setter
    def x(self, x):
        if x < 0:
            self.__x = 0
        elif x > 100:
            self.__x = 100
        else:
            self.__x = x

我的情况似乎更复杂。

class A:

    def __init__(self, x):
        self.__x = x
        self.x1()
        self.x2()
        self.x3()

    def x1(self):
        self.__x1 = self.__x + 1
        return self.__x1

    def x2(self):
        self.__x2 = self.__x1 + 2
        return self.__x2

    def x3(self):
        self.__x3 = self.__x2 + 3
        return self.__x3


if __name__ == "__main__":
    a = A(3)
    print(a.x3)

方法x1x2x3过于简化。调用self.__x3方法时,__init__变量仅设置一次。现在,我需要一个getter方法来通过调用self.__x3来获取a.x3。如何以pythonic方式实现?

1 个答案:

答案 0 :(得分:2)

尝试基于以下假设进行尝试:您只希望__x#期间不修改__init__变量,并且永远不要再修改,还希望访问器遵循相同的代码路径(可能是因为读取是在程序上也很复杂):

在这种情况下,您可以让实现函数采用附加的默认参数。以属性形式访问时,它将接收默认参数,但是如果显式访问属性的fget成员,则可以使用非默认参数来调用它。一个仅解决x1的简单示例:

class A:

    def __init__(self, x):
        self.__x = x
        # Access the property itself off the class, bypassing execution,
        # then call it directly with the non-default argument
        type(self).x1.fget(self, True)

    @property
    def x1(self, doset=False):
        if doset:
            self.__x1 = self.__x + 1
        return self.__x1

或者,为了简化__init__中的用法,可以对基础函数和property使用不同的名称,以达到相同的效果:

class A:

    def __init__(self, x):
        self.__x = x
        # Call the implementing function directly with the non-default argument
        self._x1(True)

    # Implementing function named with single underscore prefix to indicate it's
    # for internal/protected use only
    def _x1(self, doset=False):
        if doset:
            self.__x1 = self.__x + 1
        return self.__x1
    # Define property x1 based on x1 for outside use
    x1 = property(_x1)

当然,如果您没有复杂的getter路径,那么真正的解决方案是将_x1x1完全分开,其中_x1是{ {1}}和__init__是纯吸气剂:

x1

要清楚一点,在任何有意义的意义上,只有最后一个是“ Pythonic” 。第二个选项的用例有限(您有一个需要存在的函数,并且该函数高度可配置,但是具有class A: def __init__(self, x): self.__x = x # Call the init helper self._init_x1() # Implementing function named with single underscore prefix to indicate it's # for internal/protected use only def _init_x1(self): self.__x1 = self.__x + 1 @property: def x1(self): return self.__x1 可以使用的一组合理的默认值),但是在那种情况下,它通常是一个函数像property一样具有公用功能。选项#1是最少的Python语言,因为使用起来很不方便(需要提升类的类型,提取property成员,并显式地传递fget),并且很清楚没有self之外的预期用例(因为使用起来很痛苦,没人愿意打扰)。