【问题标题】:Use __getattr__ instead of a getter and still have a setter?使用 __getattr__ 代替 getter 并且仍然有 setter?
【发布时间】:2015-05-02 16:35:24
【问题描述】:

假设我的班级已经有 __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

我想让玩家的金币(例如)不会低于零。 这是它的设置器:

def gold(self, value):
    if value < 0:
        raise ValueError
    self.__setattr__('gold', value)

但是,我发现编写一个除了调用 self.__getattr__('gold') 之外什么都不做的 getter 是愚蠢的,有没有办法做到这一点,所以我不需要在这里定义其他方法?

这不仅仅是一个属性(在这个例子中是黄金),我有多个属性,而 getter 似乎只是一些额外的工作。

【问题讨论】:

  • 为什么要将每个对象的数据存储在全局字典而不是对象本身中?
  • @chepner 我正在继承一个玩家类,它基本上只是游戏本身的玩家包装器(我正在为游戏创建一个额外的插件),这个玩家类我当您需要访问播放器的数据时,始终接收一个新实例来使用子类化。所以我不能在实例中存储我的模组的金币等,因为实例总是不同的。

标签: python python-3.x properties


【解决方案1】:

如果我正确理解了您的需求(这次!),您可以执行以下操作:

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

【讨论】:

  • 啊,我想做的并不总是“保持积极”,一些我需要保持积极的属性,一些我需要确保玩家可以使用等等 :) 例如,我想防止玩家捡起他没有受过使用训练的枪。
  • 我为什么要这样做?如果我想得到玩家的武器,我只需将它归还。但是,如果我想设置它,我必须确保玩家​​可以访问它(也许我想看看它是否是他库存中的武器?)。所以我不需要任何额外的getter逻辑,但我需要一个自定义setter。并且已经有第三方应用程序使用我的代码,它们使用旧属性(我现在正在更新属性),所以我不想添加具有新名称的函数。如果其中任何一个有意义,抱歉英语不是我的母语:)
  • 我也不明白为什么要在__setattr__ 中添加任何逻辑,这就是为什么我要为那些需要一些复杂逻辑的属性创建设置器?您需要什么信息?
  • @MarkusMeskanen 抱歉,我想我误解了你的目标。这是否更符合您的要求?
  • 非常感谢,如果我的解释不好,对不起:) 但是,您的解决方案正是我想要的!我没有意识到我可以使用property 函数(或类?)本身来创建属性!谢谢,采纳! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-26
  • 2011-10-22
相关资源
最近更新 更多