全局名称'p1'未定义

0 投票
3 回答
2038 浏览
提问于 2025-04-18 05:34

我有一个函数里面又定义了一个函数(见下面的代码)。

当我运行 >>> pd = distrib(10,listAll) 的时候,我得到了这个结果(注意行号是我文件里的行号,而不是下面示例中的行号)

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "transportOpt.py", line 78, in distrib
N = NN(0,t1)
File "transportOpt.py", line 48, in NN
print(p1,p2)
NameError: global name 'p1' is not defined

这是函数的具体内容

def distrib(Nm,lf):
    l = len(lf)
    pd = {}# the output dictionary distribution
    sumpd = 0# the total number of samples

    p1=0
    p2=0
    buf=[lf[0]]
    def NN(a,b):
        global p1,p2
        print(p1,p2)
        y = max(a,b)
        x = min(a,b)
        if y>p2:
            for j in range(p2-p1+1,y-p1+1):
                buf.append(buf[j-1]+lf[j])
            p2 = y
        if x>p1:
            for j in range(0,x-p1):
                buf.pull(j)
            p1 = x
        return buf[b-p1]-buf[a-p1]

    def UpdateDistrib(a,b):
        global sumpd
        tao = t1-t0
        if tao < 0:
            print('UpdateDistrib: t1<t0: mistake')
        if tao == 0:
            tao = 1
        CurrentCount = pd.get(tao,0)
        pd[tao] = CurrentCount + 1.
        sumpd = sumpd + 1.

    def normdistrib():
        for i in pd.keys():
            num = pd[i]
            pd[i] = num/sumpd

    for t1 in range(l):
        N = NN(0,t1)
        if N>Nm:
           UpdateDistrib(0,t1)
           break
    if t1==l-1 and N<=Nm:
        normdistrib()
        return pd
    for t0 in range(1,l):
        N = NN(t0,t1)
        if N<=Nm:
            if t1==l-1:
                normdistrib()
                return pd
            r = range(t1+1,l)
            for t1 in r:
                N = NN(t0,t1)
                if N>Nm:
                    UpdateDistrib(t0,t1)
                    break
        else:
            UpdateDistrib(t0,t1)
    normdistrib()
    return pd

出什么问题了?我是不是用“global”用错了?

3 个回答

1

你需要在函数 'distrib(Nm,lf):' 之外定义 p1 和 p2。全局函数是用来改变那些在原始函数外部的变量值的,而不是用来把它们引入到子函数中的。

p1 = 0
p2 = 0

def distrib(Nm,lf):
    l = len(lf)
    pd = {}# the output dictionary distribution
    sumpd = 0# the total number of samples

    buf=[lf[0]]
    def NN(a,b):
        global p1,p2
        print p1,p2
1

你有没有在 distrib 函数外面定义 p1 呢?这可能就是你的问题,因为 p1 和 p2 仍然在 distrib 函数中被使用,它们是“封闭”的,Python 会知道该操作哪些变量。完全去掉 global 声明,应该就能正常工作了。
关于作用域的更多信息:Python 作用域规则的简要说明?
注意 LEGB 规则:局部(Local)、封闭(Enclosed)、全局(Global)、内置(Built-in)。

3

也许你认为 global p1 是让名字 p1 指向之前定义的变量 p1=0。其实并不是这样,因为之前的变量并不是全局的,它是局部的,只在函数 distrib 内有效。

在定义嵌套函数时,你不需要使用 global 来引用外部变量。不过,在 Python 2.7 中,你不能通过嵌套函数去给外部变量赋值。要做到这一点,你需要使用 nonlocal,而这个功能只在 Python 3.0 及以上版本中才有。因为在嵌套函数中对 p1 进行赋值,会导致这个名字无法指向外部函数中的 p1,而使用 global 也没有用。

撰写回答