使用 __getattr__ 而不是 getter 仍然有 setter?
Use __getattr__ instead of a getter and still have a setter?
假设我的 class 已经有 __getattr__
和 __setattr__
,就像这样:
def __getattr__(self, attr):
return _global_user_data[self.userid][attr]
def __setattr__(self, attr, value):
_global_user_data[self.userid][attr] = value
我想让玩家的金币(例如)不能降到零以下。
这是一个 setter:
def gold(self, value):
if value < 0:
raise ValueError
self.__setattr__('gold', value)
但是,我发现编写一个只调用 self.__getattr__('gold')
的 getter 是愚蠢的,有没有办法做到这一点,所以我不需要定义其他方法在吗?
不只是一个 属性(在这个例子中是黄金),我有多个属性,getter 似乎只是一些额外的工作。
如果我正确理解了您的要求(这次!),您可以这样做:
class User:
def __init__(self, id_):
self.user_id = id_
def __getattr__(self, attr):
return _global_user_data[self.user_id][attr]
def set_x(self, val):
if val < 0:
raise ValueError
_global_user_data[self.user_id]['x'] = val
x = property(lambda self: self.__getattr__('x'), set_x)
你只需要为x
定义一个特定的setter,getter只是重定向到现有的__getattr__
。请注意,这直接创建了 property
,而不是使用装饰器语法,但在其他方面做的事情完全相同。使用中:
>>> _global_user_data = {0: {'x': None}}
>>> user = User(0)
>>> user.x
>>> user.x = -1
Traceback (most recent call last):
File "<pyshell#38>", line 1, in <module>
user.x = -1
File "<pyshell#35>", line 8, in set_x
raise ValueError
ValueError
>>> user.x = 1
>>> user.x
1
假设我的 class 已经有 __getattr__
和 __setattr__
,就像这样:
def __getattr__(self, attr):
return _global_user_data[self.userid][attr]
def __setattr__(self, attr, value):
_global_user_data[self.userid][attr] = value
我想让玩家的金币(例如)不能降到零以下。 这是一个 setter:
def gold(self, value):
if value < 0:
raise ValueError
self.__setattr__('gold', value)
但是,我发现编写一个只调用 self.__getattr__('gold')
的 getter 是愚蠢的,有没有办法做到这一点,所以我不需要定义其他方法在吗?
不只是一个 属性(在这个例子中是黄金),我有多个属性,getter 似乎只是一些额外的工作。
如果我正确理解了您的要求(这次!),您可以这样做:
class User:
def __init__(self, id_):
self.user_id = id_
def __getattr__(self, attr):
return _global_user_data[self.user_id][attr]
def set_x(self, val):
if val < 0:
raise ValueError
_global_user_data[self.user_id]['x'] = val
x = property(lambda self: self.__getattr__('x'), set_x)
你只需要为x
定义一个特定的setter,getter只是重定向到现有的__getattr__
。请注意,这直接创建了 property
,而不是使用装饰器语法,但在其他方面做的事情完全相同。使用中:
>>> _global_user_data = {0: {'x': None}}
>>> user = User(0)
>>> user.x
>>> user.x = -1
Traceback (most recent call last):
File "<pyshell#38>", line 1, in <module>
user.x = -1
File "<pyshell#35>", line 8, in set_x
raise ValueError
ValueError
>>> user.x = 1
>>> user.x
1