在函数内访问全局双端队列或数据结构

1 投票
3 回答
3631 浏览
提问于 2025-04-17 23:10

我需要在主程序中创建全局的双端队列(deque),并在从这个程序调用的函数中使用它。在我的例子里,我创建了一个叫“questions”的双端队列,并往里面添加了两个列表。我在主程序中打印这个双端队列,以显示它已经成功创建并填充了内容。

在函数中,我试图把“questions”这个双端队列里的项目取出来放到一个变量“question”里,但我遇到了一个错误:“NameError: global name 'questions' is not defined”,意思是找不到这个名字。

我该如何在函数中访问这个双端队列呢?我也尝试过注释掉的“global questions”和“from collections import deque”,结果还是一样,包含或不包含这些行的各种组合都试过了。

这个函数是在一个模块里,文件结构如下:

├── problemmain.py
├── modules
│   ├── problemchild.pyc
│   ├── problemchild.py
│   ├── __init__.pyc
│   └── __init__.py

problemmain.py:

#!/usr/bin/python

# Send them to the id connector
from modules.problemchild import problem_child
from collections import deque
#idconnector_send(questions,\
#                 rmdconfig.idconnector['send_dst_hostname'],\
#                 rmdconfig.idconnector['send_dst_port'])

questions=deque()

questions.append(['item1','item2','item3',['inneritem1','inneritem2','inneritem3','inneritem4','inneritem5','inneritem6']])
questions.append(['item1','item2','item3',['inneritem1','inneritem2','inneritem3','inneritem4','inneritem5','inneritem6']])

print questions

problem_child()

#idconnector_receive(rmdconfig.idconnector['receive_dst_hostname']\
#                    rmdconfig.idconnector['receive_dst_port'])

modules/__init__.py:

#!/usr/bin/python
#__all__ = ["readconf",]

modules/problemchild.py:

#!/usr/bin/python

def problem_child():

    """Determine what's wrong with modules scope and deque
    """
#    from collections import deque
#    global questions
    while True:
            #question = questions.pop()
            question = questions.pop()
            print "Question is: "
            print question
            print "----------------------------------------------------"

输出:

./problemmain.py


deque([['item1', 'item2', 'item3', ['inneritem1', 'inneritem2', 'inneritem3', 'inneritem4', 'inneritem5', 'inneritem6']], ['item1', 'item2', 'item3', ['inneritem1', 'inneritem2', 'inneritem3', 'inneritem4', 'inneritem5', 'inneritem6']]])
Traceback (most recent call last):
  File "./problemmain.py", line 17, in <module>
    problem_child()
  File "/home/justin.h.haynes/rmd/modules/problemchild.py", line 11, in problem_child
    question = questions.pop()
NameError: global name 'questions' is not defined

尝试了Aaron的建议,替换“questions_queue”,我得到了以下结果:

$ ./problemmain.py
Traceback (most recent call last):
  File "./problemmain.py", line 13, in <module>
    modules.questions_queue=deque()
NameError: name 'modules' is not defined

3 个回答

0

为什么不把它放在一个公共的命名空间里呢?

modules.questions_queue=deque()

然后可以这样访问它:

modules.questions_queue.append(['item1'...

编辑

你需要做以下其中之一:

import modules

或者

import modules.something
2

@jonrsharpe 已经回答了这个问题,但我觉得有必要多讲讲为什么这个答案是这样的。我不想编辑问题,因为如果其他人想做同样的事情,可能找不到原来的例子。

这个问题的核心其实是“我怎么能全局访问一个双端队列(deque)”,但我会解释一下我在问更具体问题时的错误假设。这个问题本身是有效的,只是基于错误的假设和理解。

函数不应该修改全局变量(或者说全局的任何东西)。这样做的理由并不多。对于变量、列表和这里第9.1节提到的“其他大多数类型”,这都是正确的。http://docs.python.org/2/tutorial/classes.html

不过,并不是所有对象都这样。当你传递一个双端队列时,实际上只是传递了一个引用(如果我说得太简单了,请有人纠正我)。我理解这是因为引用只是命名空间中指向同一个对象的另一种指针结构。在传递双端队列的情况下,函数内部和全局空间都有一个指向它的引用。

所以我可以创建一个双端队列,添加一些元素,把它传递给一个函数,在这个函数内部对传递的双端队列添加元素,然后在函数外查看内容,证明我一直在操作同一个对象:

#!/usr/bin/python


print "-------- strings --------"
a = "this is something"

print a

def scopetest(b):
    print b + ":was passed to me"
    print "I will change it now"
    b="This is something else"
    print "now it is:"
    print b


scopetest(a)

print a


print "------- deque ----------"

from collections import deque

my_deque = deque()

print "I just made a deque called my_deque"
print "it has:"
print my_deque

my_deque.append("this is the first thing in my deque")
my_deque.append("this is the second thing in my deque")

print "I just appended a couple of lines"
print "it has now:"
print my_deque


print "now I will define a new function called scopetest_deque()"

def scopetest_deque(a):
    a.append("this is the third thing in my deque")
    a.append("this is the fourth thing in my deque")
    print "I just appended a couple of lines"
    print "it has now:"
    print a


print "Calling it now:"
scopetest_deque(my_deque)

print "it has now:"
print my_deque

在输出中,我们看到字符串是函数内部的局部变量,而在双端队列中,我们只是用不同的名字指向了同一个双端队列实例,这个实例在程序的主部分和函数内部都被修改过:

./test.py

-------- strings --------
this is something
this is something:was passed to me
I will change it now
now it is:
This is something else
this is something
------- deque ----------
I just made a deque called my_deque
it has:
deque([])
I just appended a couple of lines
it has now:
deque(['this is the first thing in my deque', 'this is the second thing in my deque'])
now I will define a new function called scopetest_deque()
Calling it now:
I just appended a couple of lines
it has now:
deque(['this is the first thing in my deque', 'this is the second thing in my deque', 'this is the third thing in my deque', 'this is the fourth thing in my deque'])
it has now:
deque(['this is the first thing in my deque', 'this is the second thing in my deque', 'this is the third thing in my deque', 'this is the fourth thing in my deque'])
0

我建议你把 questions 作为一个明确的参数来使用:

def problem_child(questions):

然后从调用的地方传递这个参数:

print questions
problem_child(questions)

通常来说,如果你觉得需要使用 global 变量,那就说明可能有些地方设计得不太好。

撰写回答