简体   繁体   English

在python函数中使用全局变量

[英]Working with a global variable inside a python function

At this code snippet: 在此代码段:

def taylorVazquez(fx,a,b,n,puntos):

    puntosX = linspace(a,b,num=puntos)
    aproxY = []
    puntosY = []    

    def toFloat():
        puntosX = [float(x) for x in puntosX]
        aproxY = [float(y) for y in aproxY]
        puntosY = [float(y) for y in puntosY]

I'm getting the error message: 我收到错误消息:

UnboundLocalError: local variable 'puntosX' referenced before assignment

And so I know same would happen to the other two variables. 所以我知道其他两个变量会发生同样的情况。 What can I do it's the outer taylorVazquez 's variables the ones I manipulate at inner function, in other words, I want the assignments to work for the outer scope too 我能做什么taylorVazquez外层taylorVazquez的变量,我在内部函数处理的变量,换句话说,我希望赋值也适用于外部作用域

Whenever you assign a value to a variable in a given scope, the variable is assumed to be local to that scope. 无论何时为给定范围内的变量赋值,该变量都假定为该范围的本地变量。 Depending on which Python you are using, you will either need to use nonlocal (Python 3) or pass the values in using parameters (Python 2). 根据您使用的Python,您将需要使用非本地(Python 3)或使用参数传递值(Python 2)。

Here is Python 2 : 这是Python 2

def toFloat(puntosX, aproxY, puntosY):  # now the names of the enclosing function can be passed to the toFloat function
    puntosX = [float(x) for x in puntosX]
    aproxY = [float(y) for y in aproxY]
    puntosY = [float(y) for y in puntosY]

In Python 3 : Python 3中

def toFloat():
    nonlocal puntosX, aproxY, puntosY  # the names now refer to the enclosing scope rather than the local scope
    puntosX = [float(x) for x in puntosX]
    aproxY = [float(y) for y in aproxY]
    puntosY = [float(y) for y in puntosY]

global will NOT work in this situation, since you are referencing the names of an enclosing function. global不会在这种情况下工作,因为你引用一个封闭的函数的名称。

One more thing, you MAY be trying to assign new values to the names in the enclosing scope. 还有一件事,您可能正在尝试为封闭范围中的名称分配新值。 Your present tactic will not work, since you are assigning new objects to these names within the innermost function. 您目前的策略不起作用,因为您要在最里面的函数中为这些名称分配新对象。 (List comprehensions create new lists.) If you need to keep the new values , you will need to (for example) return these values to the enclosing scope and reassign your original names to the new values. (列表推导创建新列表。) 如果需要保留新值 ,则需要(例如)将这些值返回到封闭范围,并将原始名称重新分配给新值。 For example, in Python 2: 例如,在Python 2中:

def taylorVazquez(fx,a,b,n,puntos):
    puntosX = linspace(a,b,num=puntos)
    aproxY = []
    puntosY = [] 

    def toFloat(puntosX, aproxY, puntosY):  # now the names of the enclosing function can be passed to the toFloat function
        puntosX = [float(x) for x in puntosX]
        aproxY = [float(y) for y in aproxY]
        puntosY = [float(y) for y in puntosY]
        return puntosX, aproxY, puntosY

    puntosX, aproxY, puntosY = toFloat(puntosX, aproxY, puntosY)  # now you can reassign these names to the new values

Unlike global , you cannot assign new values to these names and have them hold for the enclosing scope. global不同,您不能为这些名称分配新值,并将它们保留为封闭范围。

If you assign to a variable in a Python function, the interpreter assumes that it is a local variable. 如果在Python函数中赋值给变量,则解释器会假定它是局部变量。 All other uses of that variable are also assumed to be local, even ones that come before the assignment. 该变量的所有其他用法也被假定为本地的,甚至是在赋值之前的那些。 This is why you get an exception about local variable 'puntosX' referenced before assignment . 这就是为什么你得到一个关于local variable 'puntosX' referenced before assignment的例外。

There are a few possible solutions. 有一些可能的解决方案。

One is to declare the variable to be global (or in Python 3, nonlocal if its a local variable in an enclosing function). 一种是将变量声明为global变量(或者在Python 3中声明nonlocal局部变量,如果它是封闭函数中的局部变量)。

def taylorVazquez(fx,a,b,n,puntos):

    puntosX = linspace(a,b,num=puntos)
    aproxY = []
    puntosY = []    

    def toFloat():
        nonlocal puntosX, aproxY, puntosY # this fixes the UnboundLocalError

        puntosX = [float(x) for x in puntosX]
        aproxY = [float(y) for y in aproxY]
        puntosY = [float(y) for y in puntosY]

Another option is to mutate the variable in place, rather than reassigning it. 另一个选择是将变量放在适当的位置,而不是重新分配它。 For instance, you can use list.append and list.__setitem__ on a list without ever making a local reference to it. 例如,您可以在列表中使用list.appendlist.__setitem__ ,而无需对其进行本地引用。

def toFloat():
    for i, v in enumerate(puntosX):
        puntosX[i] = float(v) # this calls puntosX.__setitem__, mutating it in place

    # etc...

A last option is to unnest your functions and pass arguments and return values, rather than relying on the nested namespaces to make your values available. 最后一个选项是取消您的函数并传递参数并返回值,而不是依赖嵌套的命名空间来使您的值可用。 For instance: 例如:

def toFloat(lst):
    return [float(v) for v in lst]

# then later
puntosX = toFloat(puntosX)

You can access the variable just fine, the issue here is that in Python2 there's no way to reassign the variable. 你可以很好地访问变量,这里的问题是在Python2中没有办法重新分配变量。 There's a PEP in for fixing this issue (PEP-227) . 有一个PEP来解决这个问题(PEP-227)

It was in fact addressed in Python 3, and you could label your variables as nonlocal , but that's not a huge comfort if you're still using Python 2. 它实际上是在Python 3中解决的,您可以将变量标记为非nonlocal变量,但如果您仍在使用Python 2,那么这并不是一个巨大的安慰。

You can work around it by doing something like this: 你可以通过做这样的事情来解决它:

def f1():
    x = [1]
        def f2():
        x[0] = 2
    f2()
    print x[0]
f1()

There are also a number of other potential workarounds, but most of them will result in unexpected behavior. 还有许多其他潜在的解决方法,但其中大多数都会导致意外行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM