为了不让自己过度张扬,我将举一个我想做的基本假设假设。 假设以下类别:
class foo():
def __init__(self):
self.keywords = []
## this method returns the entire list
def get_keywords(self):
return self.keywords
def set_keywords(self, value):
self.keywords.append(value)
但是我想使用@property
装饰器以pythonic方式编写代码。
我(错误的)尝试这样做:
class foo:
def __init__(self):
self.key = []
@property
def key(self):
return self.__key
@key.setter
def key(self, value):
self.__key.append(value)
那么,我的尝试出了什么问题? ps:英语不是我的母语,我希望我的疑问可以理解。
答案 0 :(得分:1)
在您的原始代码中,self.set_keywords
仅 附加到现有列表中;它不允许您将keywords
的值初始化为任意列表。此限制保留在基于property
的代码中,这意味着您无法直接分配给self.key
;您必须直接在__init__
中初始化基础列表。
class foo:
def __init__(self):
# self.key = [] is equivalent to `self.__key.append([])`, but
# self.__key doesn't exist yet. (And would be wrong even if it did.)
self.__key = []
@property
def key(self):
return self.__key
@key.setter
def key(self, value):
self.__key.append(value)
但是,这意味着像self.key = 3
这样的作业实际上并没有执行大多数人期望的作业。它不会覆盖旧值,而是添加到旧值中。使用设置器提供一个固定列表,但使用另一种方法将其添加到现有列表中。
class foo:
def __init__(self):
self.__keys = []
@property
def keys(self):
return self.__keys
@keys.setter
def keys(self, values):
self.__keys = values
def add_key(self, value):
self.__key.append(value)
最后,如果您实际上没有在getter或setter中做任何额外的工作或验证,则使用属性不一定是Pythonic。如果您要做的只是包装对基础值的访问,只需直接使用该值即可。
class foo:
def __init__(self):
self.keys = []
self.keys = [1,2,3]
print(self.keys)
self.keys.append(4)
# etc
关于属性的好处是,如果您通过允许直接访问keys
来开始,那么关于keys
的使用方式没有任何变化如果您以后决定将其替换为属性。
答案 1 :(得分:0)
您可以尝试一下:
class Foo:
def __init__(self):
self._key = []
@property
def key(self):
return self._key
@key.setter
def key(self, value):
self._key = value
这是我的两分钱
foo
重命名为Foo
self.key
,因为这是属性,因此请在构造函数中初始化正确的变量(即__init__
)_
范围为前缀,而不是两个(两个__
是Python内部函数)my_instance.key = ['spam', 'eggs']
替换foo._key
值而不是扩展它。因为这是一个“设定者”,并且会导致怪异的行为,或者至少另一个开发人员不会期望该设定者/函数的这种行为但是,这很重要:只要您仅这样做,就不需要属性。您只需在构造函数和froget中初始化有关属性和setter函数的self.keys
即可。稍后,当您想要更改行为时,仍然可以添加属性和设置器。这就是我们在Python中拥有属性的原因之一,这样您就不必重构整个代码,以防出现“更多逻辑”。
顺便说一句。如果您真的要依赖于所有dict函数,那么您可能还想从dict
类继承您的类。取决于您的工作。