简体   繁体   English

从 function 返回多个值的非侵入式方法?

[英]Non-invasive way to return multiple values from a function?

I am dealing with a large code base and I am wondering what is a non-invasive way to add an extra return value to a function without changing all the uses.我正在处理一个大型代码库,我想知道在不更改所有用途的情况下向 function 添加额外返回值的非侵入性方法是什么。 For example:例如:

Existing setup:现有设置:

def foo():
    return 'bar'

re = foo()

My attempt:我的尝试:

def foo():
    return 'bar', 'baz'


re, _ = foo()  # re has a correct value but I had to add `, _` in all uses
re    = foo()  # Error: re is now a tuple, thus semantic has changed. 

It is very important to understand that you can only ever return a single value, that value may be a container, like a tuple, like in your second example.了解您只能返回一个值非常重要,该值可能是一个容器,如元组,就像您的第二个示例一样。 But it is always a single type.但它始终是单一类型。

If you change the return value, then you can't expect to not have downstream effects, unless you change the value to some LSP compliant subtype.如果您更改返回值,那么您不能指望不会产生下游影响,除非您将值更改为某些符合LSP的子类型。 In this case, you could return some string subtype with an extra attribute, if you don't want to break the downstream uses.在这种情况下,如果您不想破坏下游使用,您可以返回一些带有额外属性的字符串子类型

class StringWithMetadata(str):
    def __new__(cls, obj, metadata=None):
        return super().__new__(cls, obj)
    def __init__(self, obj, metadata=None):
        # note, ignoring obj
        self.metadata = metadata # or whatever appropriate name you want


def foo():
    return StringWithMetadata('bar', 'baz')

re = foo()
print(re, re.metadata)

Edit:编辑:

Seeing as you tagged this with Python 2.7 (you really should avoid this if you can), then you can either use the longform of super :看到你用 Python 2.7 标记了这个(如果可以的话你真的应该避免这个),那么你可以使用super的长形式:

return super(StringWithMetadata, cls).__new__(cls, obj)

Or just the explicit way (which you could always do):或者只是明确的方式(你总是可以这样做):

return str.__new__(cls, obj)

If the intent is to add instrumentation to a function that has aa relatively large usage footprint (ie, without changing all the code that uses that function), perhaps something along those lines might help:如果目的是向具有相对较大使用足迹的 function添加检测(即,不更改使用该函数的所有代码),那么这些方面的一些东西可能会有所帮助:

def foo(spy=None):
    result = 'bar'
    if isinstance(spy, dict):
        spy['ret'] = result
        spy['other'] = 'baz'
        # ...
    return result

Examples:例子:

The original uses can remain unchanged:原来的用途可以保持不变:

r = foo()
>>> r
'bar'

But you can also pass a dict to obtain some other info from within your function:但是你也可以通过一个字典来从你的 function 中获取一些其他信息:

spy = {}
r2 = foo(spy=spy)
>>> spy
{'ret': 'bar', 'other': 'baz'}

You can of course use other types for your "spy" container.您当然可以为您的“间谍”容器使用其他类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM