允许用户只读取python中函数返回的第一个变量

时间:2013-11-28 15:19:48

标签: python tuples return-value

我有一个函数(“愚蠢的最小例子”):

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的其他参数,也没有ff2两个函数。


在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,如我所愿。)

6 个答案:

答案 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作为现有代码。 这取决于你想做什么。