我有一个函数(“愚蠢的最小例子”):
def f(n):
a = n*n
b = a+1
return b
b0 = f(n) # used million times in the code
我希望以这样的方式更改def f() :
:
def f(n)
a = n*n
b = a+1
somemagicreturn b,a
b0 = f(n) # gives b0 == n*n+1
b0,a0 = f(n) #gives b0 == n*n+1 and a0==n*n
如果可能的话,没有f
的其他参数,也没有f
和f2
两个函数。
在Matlab中,这可以通过以下方式实现:
档案f.m
:
function [r1,r2]=f(n)
if nargout == 2,
r1 = n*n+1
r2 = n*n
else,
r1 = n*n+1
end,
甚至更简单:
function [r1,r2]=f(n)
r1 = n*n+1
r2 = n*n
以上两者均用作:
b = f(0)
[b,a] = f(0)
(第一个返回b=1
,第二个b=1, a=0
,如我所愿。)
答案 0 :(得分:3)
抱歉,我目前无权添加评论。
我可以修改功能f吗?
如果是,您可以添加具有默认值的关键字选项:
def f(n, nopt=2):
a = n^2
b = b+1
if nopt == 2 :
return b,a
else :
return b
答案 1 :(得分:2)
另一种解决方法,它解析调用它的代码并且需要绝对没有修改调用f()的代码。它使用inspect和ast模块,因此为它们添加导入。
inspect.stack()[2 if called_from_function else 1][4][0]
获取正在调用f()
的代码。
import inspect
import ast
def num_assigns():
calling_code = inspect.stack()[2][4][0]
calling_code = calling_code.lstrip() # Strip the identation
first = ast.parse(calling_code).body[0]
blocks = (ast.FunctionDef, ast.ClassDef, ast.For, ast.While, ast.If, ast.While, ast.TryExcept, ast.TryFinally)
# Handle the case of the assignment being in a block
if isinstance(first, blocks):
first = first.body[0]
if not isinstance(first, ast.Assign): return 0
targets = first.targets
if isinstance(targets[0], ast.Tuple):
return len(targets[0].elts)
if isinstance(targets, list):
return len(targets)
assert False, "This part should never be reached"
def fruits():
print(num_assigns())
return "apple", "orange"
if True:
apple, orange = fruits()
只需从f()调用num_assigns(),找出返回值分配给的值的数量。请注意,它不能在Python交互式控制台中工作,因为num_assigns()从文件中读取代码。此外,num_assigns()假定它是从函数调用的,如果没有,则将called_from_function参数设置为False。
答案 2 :(得分:1)
只需传递函数所需的返回值的数量:
def f(returns=1, n):
a = n**2
b = a+1
return (a, b)[:returns]
使用returns
作为要返回的值的数量。
答案 3 :(得分:1)
我正在做出不同的答案,因为这是一种不同的方法。 所有学分都是here,我只是根据你的情况调整了。
到目前为止,可能不是恕我直言的最佳做法。
import inspect, dis
def expecting():
"""Return how many values the caller is expecting"""
f = inspect.currentframe()
f = f.f_back.f_back
c = f.f_code
i = f.f_lasti
bytecode = c.co_code
instruction = ord(bytecode[i + 3])
if instruction == dis.opmap['UNPACK_SEQUENCE']:
howmany = ord(bytecode[i + 4])
return howmany
elif instruction == dis.opmap['POP_TOP']:
return 0
return 1
def f(n):
howmany = expecting()
a = n * n
b = a + 1
if howmany == 1:
return b
else:
return b, a
a = f(1)
print a # this prints 2
a, b = f(1)
print a # this prints 2
print b # this prints 1
答案 4 :(得分:0)
我认为不可能返回两个值并使其仅接收第一个值,但您可以添加:
global a0
the code for computing a
a0 = a
然后在调用函数后,a0将被设置为a。
答案 5 :(得分:0)
你可以这样做:
def g(n):
a = n*n
b = a+1
return b,a
def f(n):
b,_ = g(n)
return b
这样,您可以在需要所有答案时使用g
,并继续使用f
作为现有代码。
这取决于你想做什么。