我们可以使用@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)
方法x1
,x2
和x3
过于简化。调用self.__x3
方法时,__init__
变量仅设置一次。现在,我需要一个getter方法来通过调用self.__x3
来获取a.x3
。如何以pythonic方式实现?
答案 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路径,那么真正的解决方案是将_x1
与x1
完全分开,其中_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
之外的预期用例(因为使用起来很痛苦,没人愿意打扰)。