Properties 从数组创建python属性,共享getter和setter?
我一直在编写一个python脚本,每次更改某些值时,都应该修改一个并行值。例如:Properties 从数组创建python属性,共享getter和setter?,properties,python-3.6,Properties,Python 3.6,我一直在编写一个python脚本,每次更改某些值时,都应该修改一个并行值。例如: self.empire.gold = 345 self.empire.update_times.gold = time.time() 每次这样做都会让人感到痛苦,所以我一直在研究如何让这一切自动发生。这就是我想到的: import time class boring_object: pass class Object: def __init__(self, gold): s
self.empire.gold = 345
self.empire.update_times.gold = time.time()
每次这样做都会让人感到痛苦,所以我一直在研究如何让这一切自动发生。这就是我想到的:
import time
class boring_object:
pass
class Object:
def __init__(self, gold):
self._gold = gold
self._updates = boring_object()
@property
def gold(self):
return self._gold
@gold.setter
def gold(self, value):
self._gold = value
self._updates.gold = time.time()
使用这个,我可以自动更新时间
然而,我也希望将类似的setter应用于其他一些资源
我可以将此代码复制五次以覆盖黄金,谷物,土豆,等等,但我只想将一个资源名称数组传递给构造函数,并让它们共享通用的getter和setter。可能吗
在实现这些之前,我使用了一些更接近于无聊的对象()
:
除了缺少属性功能之外,这也不能很好地print()
。对于一个既可以使用通用的getter和setter,又可以在不需要太多额外代码的情况下很好地打印的解决方案来说,这是一个额外的好处
一旦我写了这篇文章,我发现了关于能手和二传手。一个答案是这样的,这将使我更接近我的目标,但我不想存储更新时间,也不想改变我最终在这个对象上设置的所有属性——只是初始化它时命名的属性。其他属性的行为应该像没有自定义的getter/setter逻辑一样。\uuu getattr\uuuu
等等都是很好的神奇方法,可以让你变得聪明。然而,我建议你不要这样做。它们使您的代码难以理解和遵循。想象一下其他人(或一年后的你)试图理解。如果有一个明确的、易于理解的方法来完成工作,我总是希望这样
如果您想限制对属性的访问或向其添加一些小逻辑,比如存储更新时间,那么python@属性
很好。然而,属性并不真正适合您的情况,因为您需要一些动态的东西,并且可以在运行时进行配置。那么为什么不使用显而易见的方法呢?一些“私人”字典(见下面的\u财产
和\u更新
)如何简单地存储帝国的资源
因此,以下是我对如何解决您的问题的建议:
import time
class Empire(object):
def __init__(self, resources):
self._possessions = {r: 0 for r in resources}
self._updates = {r: None for r in resources}
def update(self, resource, value):
if resource not in self._possessions:
raise ValueError('Your mighty Empire has no clue what {}'
' really is and how to handle'
' it.'.format(resource))
self._possessions[resource] = value
self._updates[resource] = time.time()
def get(self, resource):
if resource not in self._possessions:
raise ValueError('Your poor empire has no {}.'.format(resource))
return self._possessions[resource]
# Some use cases:
my_little_kingdom = Empire(('gold', 'celebrities', 'vanilla_ice'))
print(my_little_kingdom._updates['gold'])
my_little_kingdom.update('gold', 10)
print(my_little_kingdom.get('gold'))
print(my_little_kingdom._updates['gold'])
try:
my_little_kingdom.update('bitcoin', 42)
except ValueError as e:
print(e)
如果坚持属性访问(第一次编辑)
顺便说一句,如果您真的非常想使用花哨的\uuuu getattr\uuuuuu
和\uuuu setattr\uuuuu
方法,您可以通过
def __getattr__(self, item):
try:
return self.get(item)
except ValueError as e:
# We are trying to get an attribute, so better
# raise the corresponding error here.
raise AttributeError(str(e))
def __setattr__(self, key, value):
if key in ('_possessions', '_updates'):
# We need to do this to avoid infinite loops.
# You do see how quickly this gets really complicated!?
return super().__setattr__(key, value)
try:
self.update(key, value)
except ValueError as e:
raise AttributeError(str(e))
\uuuu setattr\uuuu
的问题在这里变得非常明显。我们需要检查真实属性以避免无限循环。这样的东西会让你的代码非常复杂。无论如何,如果您将这两种神奇的方法添加到您的帝国
,您现在就可以做到:
my_little_kingdom.gold = 123
print(my_little_kingdom.gold)
print(my_little_kingdom._updates['gold'])
try:
my_little_kingdom.balloons = 99
except AttributeError as e:
print(e)
奖励积分:可打印帝国(第二次编辑)
当然,要打造一个可打印的帝国,只需添加以下方法:
def __str__(self):
possessions = ', '.join('{value} {key}'.format(value=p[1],
key=p[0])
for p in self._possessions.items())
return ('A glorious and filthy rich empire '
'owning {}.'.format(possessions))
现在你可以通过
print(my_little_kingdom)
要了解这一点:
一个拥有123黄金、0名人、0香草冰淇淋的光荣而肮脏的帝国。
我同意Smcatepillar,只要您不需要在运行时添加新资源(如黄金、白银等),我就避免使用(g | s)Ettr_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,我不明白?只要对你的\uuuu getattr\uuuuu
和\uuu setattr\uuuuuuu
进行保护,只接受你初始化对象时使用的值。@AChampion和其他属性的行为就好像没有自定义的\uuu getattr\uuuuuu
或\uuuu setattr\uuuuuuu
一样。是的,它非常复杂,这就是我在这里问的原因。我不明白你的代码是如何处理真实属性的。\uuuu getattr\uuuu
和\uuuu setattr\uuuuu
之间的区别在于,只有当你想要的属性不是真实属性时才会调用\uu getattr\uuuuu
。但是,如果您执行类似于foo.bar=42
的操作,则始终会调用\uuuuuu setattr\uuuuuuuuuu
。所以我们需要检查是否输入(“'u财产','u更新')
,否则即使调用帝国的构造函数也会导致无限循环。为什么?因为第一个语句self.\u ownections={…}
将调用\uuu setattr\uuuu
,后者随后将调用update
update
依次使用self.\u Occupations[…]=…
,这将使您返回到\uuuuuuuSetAttr\uuuuuuuAttr
等等。我想使用属性,因为我想循环查看属性名称列表并使用setattr为什么要循环查看属性?这将涉及使用并可能实现\uuuuu dir\uuuu
。你的项目将变得很难理解。为什么不按照我的回答直接使用字典来存储资源呢?为什么你需要一个简单问题的复杂解决方案?
print(my_little_kingdom)