【问题标题】:Method chaining and accessing variables方法链接和访问变量
【发布时间】:2024-01-02 22:26:01
【问题描述】:

我认为用一个简单的例子来解释我想要实现的目标对我来说更容易。考虑以下代码:

class Person(object):
    def __init__(self):
        self._age = None
        self._gender = None

    def age(self, value):
        self._age = value
        return self

    def gender(self, value):
        self._gender = value
        return self


p = Person().age(10).gender("male")

assert p.age == 10
assert p.gender == "male"

显然断言失败是因为属性引用了方法而不是变量。 我曾尝试弄乱 __getattribute__ 方法,以便将“age”解析为“_age”,但我似乎无法找到两种情况都适用的方法,而且我不完全确定它是否可能,但 Python 让我感到惊讶我以前。

【问题讨论】:

  • 如果您真的想使用数据隐藏,这里有一个 example 属性,可以帮助您入门。

标签: python method-chaining


【解决方案1】:

简短的回答:不要。你会遇到问题,每个使用/阅读你的代码的人都会遇到问题,而且你花时间去实现它是不值得的。


长答案:如果您绝对必须,您可以创建一个在调用时设置属性值的类,否则会模仿该值的行为。为此,您必须覆盖 all magic methods,即使这样,print(type(p.age)) 之类的东西也不会产生 <class 'int'> 的预期输出。

这是一个帮助您入门的 sn-p(仅实现了 __eq__ 方法):

class CallableAttribute:
    def __init__(self, owner, name):
        self.owner= owner
        self.name= name

        setattr(owner, name, self)
        self(None)

    def __call__(self, value):
        setattr(self.owner, '_'+self.name, value)
        return self.owner

    @property
    def _value(self):
        return getattr(self.owner, '_'+self.name)

    def __eq__(self, other):
        return self._value==other

class Person(object):
    def __init__(self):
        CallableAttribute(self, 'age')
        CallableAttribute(self, 'gender')

【讨论】:

  • 您可能是对的,我可能应该重新考虑设计选择。一个简短的后续问题:如果我添加:assert p.age * 2 == 20,我得到 TypeError: unsupported operand type(s) for *: 'instance' and 'int' - 有没有办法在举止优雅?
  • @MattImmer 是的,您只需覆盖 __mul__ 函数。
  • 谢谢!我会注意到这样做是可能的,但这是一种不好的做法,并且可能会考虑替代设计。
最近更新 更多