【问题标题】:How to pass value out of a function without using return?如何在不使用返回的情况下将值从函数中传递出去?
【发布时间】:2017-10-12 00:13:56
【问题描述】:

我创建了一组相互调用价格选项的函数。其中一个函数运行了一段时间以优化一些参数(使用 Nelder Mead)。在这个函数中,计算了一个值,我想在其他一些函数中使用它,但我不想通过 return 语句将它传递出去。我认为使用 global var 会很完美。

现在,奇怪的部分是:当我通过 import * 加载作为包编写的函数时,我无法访问该函数创建的全局变量。如果我使用带有函数定义的脚本,运行它以在我的 Python 控制台中定义函数,然后调用函数,则全局 var 构造工作正常。可能是什么问题,为什么我将函数加载/定义为包还是“手动”会有所不同?

作为包加载时出错:NameError: name 'h_out' is not defined

global h_out
h_out=None
import hngoption

prices = timeseries[data.Date[i]:].head(30)
output = hngoption.params(prices) 

params() calls function LogLike() as part of its computations which contains:

def LogLike(B, r):
        # (...)
        for i in range(N - 3, -1, -1):
            h[i] = B[0] + B[2] * h[i + 1] + B[1] * pow(Z[i + 1] - B[3] * sqrt(h[i + 1]), 2)
            Z[i] = (ret[i] - r - B[4] * h[i]) / (h[i] ** 0.5)
            L[i] = -log(h[i]+ 0.000000000000001) - (ret[i] ** 2) / h[i]

        LogL = VecSum(L)

        global h_out       #IMPORTANT PART
        h_out = h[0]

        if ((B[0] < 0) | (B[1] < 0) | (B[2] < 0) | (B[3] < 0) | (B[4] < 0)):  # (B[2]+B[1]*pow(B[3],2)>=1))

            return 1e50
        else:
            return -LogL  # Minimize -Log-Like(Beta)

完整的LogLike函数:

def LogLike(B, r):

    N = len(timeseries)  #timeseries is a global var
    # Calculate S&P500 returns
    ret = [0.0] * (N - 1)
    for i in range(0, N - 1):
        ret[i] = (log(timeseries.ix[i] / timeseries.ix[i + 1]))

    Variance = VecVar(ret)
    h = [0 * i for i in range(N - 1)]
    Z = [0 * i for i in range(N - 1)]
    L = [0 * i for i in range(N - 1)]

    # Construct GARCH(1,1) process by working back in time
    h[N - 2] = Variance
    Z[N - 2] = (ret[N - 2] - r - B[4] * h[N - 2]) / h[N - 2] ** 0.5
    L[N - 2] = -log(h[N - 2]) - (ret[N - 2] ** 2) / h[N - 2]

    for i in range(N - 3, -1, -1):
        h[i] = B[0] + B[2] * h[i + 1] + B[1] * pow(Z[i + 1] - B[3] * sqrt(h[i + 1]), 2)
        Z[i] = (ret[i] - r - B[4] * h[i]) / (h[i] ** 0.5)
        L[i] = -log(h[i]+ 0.000000000000001) - (ret[i] ** 2) / h[i]

    LogL = VecSum(L)

    global h_out       #IMPORTANT PART
    h_out = h[0]


    if ((B[0] < 0) | (B[1] < 0) | (B[2] < 0) | (B[3] < 0) | (B[4] < 0)):  # (B[2]+B[1]*pow(B[3],2)>=1))

        return 1e50
    else:
        return -LogL  # Minimize -Log-Like(Beta)

【问题讨论】:

  • 请不要在截图中给出代码。相反,将代码发布在问题本身中,最好是构成minimal reproducible example的代码。
  • 您还应该解释为什么您不想使用 return,因为这是从函数返回数据的明显方式。
  • 主要是因为 NelderMead 调用此函数并从返回值中传递另一个参数会使相互调用的函数链变得非常复杂。
  • 使用return 不要使用全局状态。

标签: python python-3.x function global-variables


【解决方案1】:

您可以使用以下类型的参数来携带结果。

def test(a):
    a[0]=a[0]+2

>>> a = [2]
>>> test(a)
>>> a
[4]

【讨论】:

    【解决方案2】:

    from somemodule import * 将当时存在的somemodule 中的全局变量绑定到当前模块中的同名变量。尚未创建的变量不会被导入。如果另一个模块中的变量被重新分配,当前模块现在有自己的对不受影响的对象的引用。

    要解决您的问题,请在全局范围内为 h_out 分配一些默认值,以便其他模块在您的函数完成之前引用它时不会出错。并通过模块访问变量以获取共享值,而不是进行通配符导入。

    somemodule.py

    h_out = None
    
    def LogLikeDeep(B, r):
        global h_out       #IMPORTANT PART
        h_out = h[0]
    

    用法

    >>> import somemodule
    >>> somemodule.h_out
    >>> print(repr(somemodule.h_out))
    None
    >>> somemodule.LogLikeDeep('foo', 'bar')
    >>> print(repr(somemodule.h_out))
    'foo'
    

    【讨论】:

    • global h_out h_out = None def LogLike(B, r): global h_out h_out = h[0] (...)
    • 谢谢,我实现了这个,但是当我调用 hngoption.h_out 时它返回空而不是值。代码:全局 h_out h_out = None def LogLike(B, r): global h_out h_out = h[0] (...)
    • ...并且该函数已被调用?用一个工作示例更新您的问题怎么样,然后我们可以看到发生了什么。
    • 感谢您的回复,我更新了我的帖子,请找到上面代码的更丰富的摘录(完整代码太长,无法发布,需要数据)。谢谢你的帮助
    • 还有什么我应该添加的以使发现错误成为可能吗?感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 1970-01-01
    • 2017-01-18
    • 2020-09-10
    相关资源
    最近更新 更多