使用 __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