从函数中 return 多个值的非侵入式方法?
Non-invasive way to return multiple values from a function?
我正在处理一个大型代码库,我想知道在不改变所有用途的情况下向函数添加额外 return 值的非侵入性方法是什么。例如:
现有设置:
def foo():
return 'bar'
re = foo()
我的尝试:
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.
了解您只能 return 一个值非常重要,该值可能是一个容器,如元组,就像您的第二个示例中那样。但始终是单一类型。
如果您更改 return 值,那么您不能期望没有下游影响,除非您将该值更改为某些 LSP 兼容子类型。在这种情况下,如果您不想破坏下游用途,您可以 return 一些具有额外属性的 字符串子类型 。
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)
编辑:
看到你用 Python 2.7 标记了这个(如果可以的话你真的应该避免这个),那么你可以使用 super
:
的长格式
return super(StringWithMetadata, cls).__new__(cls, obj)
或者只是明确的方式(你总是可以这样做):
return str.__new__(cls, obj)
如果目的是添加工具到一个使用量相对较大的函数(即,不更改使用该函数的所有代码),也许是那些行可能有帮助:
def foo(spy=None):
result = 'bar'
if isinstance(spy, dict):
spy['ret'] = result
spy['other'] = 'baz'
# ...
return result
示例:
原来的用途可以保持不变:
r = foo()
>>> r
'bar'
但是你也可以传递一个字典来从你的函数中获取一些其他信息:
spy = {}
r2 = foo(spy=spy)
>>> spy
{'ret': 'bar', 'other': 'baz'}
您当然可以为您的“间谍”容器使用其他类型。
我正在处理一个大型代码库,我想知道在不改变所有用途的情况下向函数添加额外 return 值的非侵入性方法是什么。例如:
现有设置:
def foo():
return 'bar'
re = foo()
我的尝试:
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.
了解您只能 return 一个值非常重要,该值可能是一个容器,如元组,就像您的第二个示例中那样。但始终是单一类型。
如果您更改 return 值,那么您不能期望没有下游影响,除非您将该值更改为某些 LSP 兼容子类型。在这种情况下,如果您不想破坏下游用途,您可以 return 一些具有额外属性的 字符串子类型 。
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)
编辑:
看到你用 Python 2.7 标记了这个(如果可以的话你真的应该避免这个),那么你可以使用 super
:
return super(StringWithMetadata, cls).__new__(cls, obj)
或者只是明确的方式(你总是可以这样做):
return str.__new__(cls, obj)
如果目的是添加工具到一个使用量相对较大的函数(即,不更改使用该函数的所有代码),也许是那些行可能有帮助:
def foo(spy=None):
result = 'bar'
if isinstance(spy, dict):
spy['ret'] = result
spy['other'] = 'baz'
# ...
return result
示例:
原来的用途可以保持不变:
r = foo()
>>> r
'bar'
但是你也可以传递一个字典来从你的函数中获取一些其他信息:
spy = {}
r2 = foo(spy=spy)
>>> spy
{'ret': 'bar', 'other': 'baz'}
您当然可以为您的“间谍”容器使用其他类型。