Accessing a global deque or data structure from within a function

I have a need to create global deques in a main program and use them in functions called from that program. In my example, I create a deque, "questions", and add two lists to the deque. I print the deque from the main program to show that it was successfully created and populated.

In the function I attempt to pop the items off the deque "questions" and into a variable, "question" but I get a "NameError: global name 'questions' is not defined"

How can I access the deque in the function? The commented out "global questions" and "from collections import deque" have also been tried with the same result and all the permutations of including or excluding those lines.

The function is in a module, and the file structure is as follows:

├── 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 "----------------------------------------------------"

Output:

./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

Trying Aaron's suggestion, and replacing "questions_queue" I get the following:

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

Answers


I would suggest you make questions an explicit argument:

def problem_child(questions):

and pass it from the caller:

print questions
problem_child(questions)

It is generally a bad sign that you feel the need to use global variables.


Why not stick it in a common namespace?

modules.questions_queue=deque()

And then access it like this:

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

Edit

You'll need to either

import modules

or

import modules.something

@jonrsharpe has answered the question, but I thought it would be constructive to go into a bit more on the thought process for why this was the answer, and I did not think it appropriate to edit the question as a user who may try to do the same thing would not find the original example.

The spirit of this question is really "how do I access a deque globally", but here I will explain what was wrong with my assumptions when I asked my more specific question above. The question was still valid - just based on wrong assumptions and understanding.

Functions should not be modifying global variables (or global anything really). There aren't very many good reasons to be doing this. With variables, lists and "most other types" mentioned in section 9.1 here (http://docs.python.org/2/tutorial/classes.html) this is true.

However, this is not true of all objects. when one passes a deque, only the reference is passed (someone may correct me if I am oversimplifying). The way I understand this is that the reference is simply another pointerlike construct in a namespace refering to the same object. In the case of passing a deque, there is a reference it it now inside the function and in the global space.

So I can create a deque, add some elements, pass it to a function, add elements to the deque I passed within the function, and then outside the function look at the contents and prove that I was operating on the same object all along:

#!/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

And in the output we see the strings are local to the function while in the deque we simply have a different name for the same instance of deque which we have modified in both the main part of the program and from within the function:

./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'])

Need Your Help

Android: How to populate a layout with different string value files?

android android-layout android-fragments android-listview

I'm designing an app that holds contact and menu information for about 15 different restaurants. All the code i have done so far works as I would like it to, but I'm having trouble with the theory of

Sending array over MPI point to point communication

c mpi

Hi I am trying to send the edges of a 2-dim array over point to point communcation with MPI.