我明白我在这里问的可能不是最好的代码设计,但我问的原因是严格的学术。我试图了解如何使这个概念发挥作用。
通常,我将从self类方法返回,以便可以将以下方法链接在一起。我的理解是通过返回 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)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我将得到一个AttributeError: 'tuple' object has no attribute 'newmethod'预期,因为该methoda方法返回一个没有任何方法或属性的元组称为newmethod。
我的问题不是关于解包多个返回,而是更多关于当前面的方法返回多个值时如何继续链接方法。我也明白我可以通过一个参数来控制方法返回,但这不是我想要做的。
如前所述,我确实意识到这可能是一个糟糕的问题,如果问题没有任何意义,我很乐意删除该帖子。
按照@JohnColeman 的建议,如果它不是普通的元组属性,您可以返回一个特殊的元组,并委托给您的对象进行属性查找。这样它就像一个普通的元组,除非你在链接方法。
您可以按如下方式实现:
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)
Run Code Online (Sandbox Code Playgroud)
测试:
>>> t = Test()
>>> t.methoda().newmethod()
>>> print(t.hold)
lollol
Run Code Online (Sandbox Code Playgroud)
返回的结果确实作为一个元组:
>>> t = Test()
>>> t.methoda().newmethod()
>>> print(t.hold)
lollol
Run Code Online (Sandbox Code Playgroud)
你可以想象各种语义,例如使用闭包将返回值转发到链中的下一个方法:
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
Run Code Online (Sandbox Code Playgroud)
例如,
>>> t, res = t.methoda().newmethod()
>>> print(res)
2
>>> print(isinstance(t.methoda().newmethod(), tuple))
True
Run Code Online (Sandbox Code Playgroud)
会产生
>>> t = Test()
>>> t.methoda().methodb('catz')
lol catz
Run Code Online (Sandbox Code Playgroud)
如果您能让 ChainResults 不可见,那就太好了。您几乎可以通过使用正常结果初始化元组基类并将对象保存在仅用于链接的单独属性中来完成。然后使用一个类装饰器,用ChainResults(self, self.method(*args, **kw)). 对于返回元组的方法来说它可以正常工作,但单个值返回将像长度为 1 的元组一样,因此您将需要类似obj.method()[0]或result, = obj.method()使用它的东西。我尝试将元组委托给多个返回或值本身以获取单个返回;也许它可以工作,但它引入了太多的歧义,我怀疑它是否能很好地工作。
| 归档时间: |
|
| 查看次数: |
1642 次 |
| 最近记录: |