在Matlab中,nargout是一个变量,它告诉你输出是否已分配,所以
x = f(2);
和
f(2);
行为可能不同。
是否有可能在Python中做类似的事情?
我有一个绘制屏幕并返回matplotlib图形对象的函数。我希望如果将输出分配给变量,则不要绘制到屏幕。
答案 0 :(得分:4)
这是你可以做的一种方式(不是我建议它),但它有很多情况下它不起作用 - 使它工作你基本上需要解析该行中的python代码,看看它在做什么,这可能会达到某种程度,但总有可能总是有办法绕过它。
import inspect, re
def func(x, noCheck=False):
if not noCheck:
#Get the line the function was called on.
_, _, _, _, lines, _ = inspect.getouterframes(inspect.currentframe())[1]
#Now we need to search through `line` to see how the function is called.
line = lines[0].split("#")[0] #Get rid of any comments at the end of the line.
match = re.search(r"[a-zA-Z0-9]+ *= *func\(.*\)", line) #Search for instances of `func` being called after an equals sign
try:
variable, functioncall = match.group(0).split("=")
print variable, "=", functioncall, "=", eval(functioncall.strip()[:-1] + ", noCheck=True)")
except:
pass #print "not assigned to a variable"
#Actually make the function do something
return 3*x**2 + 2*x + 1
func(1) # x = func(1)
x = func(1)
另一种方法是在调用代码时检查所有设置的局部变量,并检查是否有任何设置为函数的结果,然后使用该信息来帮助解析python。
或者您可以查看对象ID,并尝试以这种方式执行操作,但这不是直截了当的,因为并非所有对象都以相同的方式工作(即执行a=10
和c=10
并且然后查看每个对象的ID,尽管a
和c
是分开的,但它们是相同的。对于短字符串也是如此。
如果你能想出一个可以普遍运作的方法,我会有兴趣知道你是怎么做的,我应该通过挖掘检查来完成,而不是通过解析实际代码。
答案 1 :(得分:1)
其他人提到这很复杂,但可以通过检查来完成。您可能需要一个简单的方法,通过单独的函数来绘制它,或者传递一个额外的变量来表示绘图。
def create_plot(x):
return plot
def display(plot):
# show the plot
x = create_plot(2)
display(x)
绘制变量
def plot(x, show=False)
# create the plot
if show:
# show the plot
plot(2, True)
x = plot(2)
可能不值得花时间而且更容易创建这两个函数。
就个人而言,我认为这很丑陋,令人讨厌,我不相信功能应该基于捕获返回值的东西。但是,我很好奇,我找到了办法。如果你想在将来使用它,你可能会把它变成一个装饰器,但我仍然建议你使用两个单独的方法而不是检查输出。
import inspect
def f(val):
has_output = False
frame = inspect.currentframe()
name = frame.f_code.co_name
outer = inspect.getouterframes(frame)[1] # may want to loop through available frames.
for i in range(len(outer)):
item = str(outer[i]).replace(" ", "")
check = "="+name+"("
if check in item and "="+check not in item: # also check assignment vs equality
# Your method has an output
has_output = True
break
if has_output:
print("Something catches the output")
return val*val
# end f
在许多情况下,这也不起作用。如果你总是想让它起作用,你必须为支票制作非常好的正则表达式。
import my_lib
x = my_lib.f(2)