python - 如何在方法链接时在 python 类方法中返回 self 和另一个变量?

标签 python

我知道我在这里问的可能不是最好的代码设计,但我问的原因是严格的学术性的。我试图了解如何使这个概念发挥作用。

通常,我会返回 self从一个类方法中,以便可以将以下方法链接在一起。我的理解是通过返回自我,我只是返回类的一个实例,以便以下方法起作用。

但在这种情况下,我试图弄清楚如何返回 self以及该方法的另一个值。这个想法是,如果我不想链接,或者我不调用任何类属性,我想从被调用的方法中检索数据。

考虑这个例子:

class Test(object):
    def __init__(self):
        self.hold = None

    def methoda(self):
        self.hold = 'lol'
        return self, 'lol'

    def newmethod(self):
        self.hold = self.hold * 2
        return self, 2

t = Test()
t.methoda().newmethod()
print(t.hold)

在这种情况下,我会得到一个 AttributeError: 'tuple' object has no attribute 'newmethod'这是可以预料的,因为 methoda方法返回一个元组,它没有任何方法或属性,称为 newmethod .

我的问题不是关于解包多个返回,而是更多关于当前面的方法返回多个值时如何继续链接方法。我也明白我可以控制方法返回一个参数,但这不是我想要做的。

如前所述,我确实意识到这可能是一个糟糕的问题,如果这个问题没有任何意义,我很乐意删除该帖子。

最佳答案

按照@JohnColeman 的建议,如果它不是普通的元组属性,您可以返回一个带有属性查找的特殊元组委托(delegate)给您的对象。这样它就像一个普通的元组,除非你链接方法。

您可以按如下方式实现:

class ChainResult(tuple):
    def __new__(cls, *args):
        return super(ChainResult, cls).__new__(cls, args)
    def __getattribute__(self, name):
        try:
            return getattr(super(), name)
        except AttributeError:
            return getattr(super().__getitem__(0), name)


class Test(object):
    def __init__(self):
        self.hold = None

    def methoda(self):
        self.hold = 'lol'
        return ChainResult(self, 'lol')

    def newmethod(self):
        self.hold = self.hold * 2
        return ChainResult(self, 2)

测试:
>>> t = Test()
>>> t.methoda().newmethod()
>>> print(t.hold)
lollol

返回的结果确实充当元组:

>>> t, res = t.methoda().newmethod()
>>> print(res)
2
>>> print(isinstance(t.methoda().newmethod(), tuple))
True

你可以想象各种语义,例如使用闭包将返回的值转发到链中的下一个方法:
class ChainResult(tuple):
    def __new__(cls, *args):
        return super(ChainResult, cls).__new__(cls, args)
    def __getattribute__(self, name):
        try:
            return getattr(super(), name)
        except AttributeError:
            attr = getattr(super().__getitem__(0), name)
            if callable(attr):
                chain_results = super().__getitem__(slice(1, None))
                return lambda *args, **kw: attr(*(chain_results+args), **kw)
            else:
                return attr

例如,

class Test:
    ...
    def methodb(self, *args):
        print(*args)

会产生
>>> t = Test()
>>> t.methoda().methodb('catz')
lol catz

如果您可以使 ChainResults 不可见,那就太好了。您几乎可以通过使用正常结果初始化元组基类并将对象保存在仅用于链接的单独属性中来做到这一点。然后使用一个类装饰器,用 ChainResults(self, self.method(*args, **kw)) 包装每个方法。 .对于返回元组的方法来说它可以正常工作,但单个值返回将像长度为 1 的元组一样,所以你需要像 obj.method()[0] 这样的东西或 result, = obj.method()使用它。我在委托(delegate)元组进行多次返回或对值本身进行单次返回方面进行了一些尝试;也许它可以工作,但它引入了太多的歧义,我怀疑它是否能很好地工作。

关于python - 如何在方法链接时在 python 类方法中返回 self 和另一个变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59259021/

相关文章:

python - 格式化字符串的最 Pythonic 方式

python27从.bat打开程序并关闭.exe

python - Python 中的枚举无法按预期工作

python - Python中整数变量的默认初始值?

python - 如何将数据框行转换为标题?

python - 在 Python 3 中使用 ANSI 序列确定终端光标位置

python - Codecademy 循环 8/19

Python 模块存储库

python - ElasticSearch/Python 动态过滤器数量

python - 如何从行首删除两个字符