Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
411 views
in Technique[技术] by (71.8m points)

python - Dynamic global variables assignment

I'm new in python and I'm having many troubles in using global instruction.
Here is a code example:

mouse = "a"
background = "b"

list_ab = [mouse, background]

def func ():
    for item in list_ab:
        global item  # I want to modify the GLOBAL item, which is mouse
                     # and background.
        item = "modified"
    print mouse  # must be "modified" not "a"
    print background  # must be "modified" not "b"

This is the problem. How can I solve it?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your problem is that Python works not the way you think.
So I will try to explain what's going on in your code, line by line.

mouse = "a"

Assigns the string "a" to the name mouse.

background = "b"

Assigns the string "b" to the name background.

list_ab = [mouse, background]

Assigns two objects, referenced by names mouse and background, to the list list_ab.
As we already know, they are constants "a" and "b". So you can just write:

list_ab = ["a", "b"]

Now the loop

for item in list_ab:

assigns each object in the list to the name item.
For the first loop iteration, it means item = "a".

The line

    global item # I want to modify the GLOBAL item, which is mouse ad background

doesn't make sense, because it tries to tell Python that the name item is global, while there is no such global variable declared.

And for the most confusing behavior on the line

    item = "modified"

you should just understand that while it assigns the string "modified" to the name item, strings "a" and "b" are still the same, and still assigned to the list list_ab (and names mouse and background, which you didn't touch either).

The name item itself lives only in the scope where it was declared, when the "for" loop ends, it's destructed. It is also reassigned every iteration with the next item from the list_ab.

To sum it up:

If you want to assign "modified" string to the items in the list, do it directly:

list_ab[0] = "modified"
list_ab[1] = "modified"

If you need to change variable declared in the global scope, do this:

mouse = "a"

def func():
    global mouse   # tell Python that you want to work with global variable
    mouse = "modified"

func()
print mouse # now mouse is "modified"

Example based on the first revision of the question:

Instead of

background = g_base("bg.jpg") # g_base class instance
mouse = g_base("mouse.png",alpha=1) # g_base class instance

imgs_to_load = [mouse, background]

def Image_loader (img):
    # ..... code to load the image and convert it into pygame surface...
    return img_load

def main ():
    for image in img_to_load:
        global image
        image = Image_loader (img)
        print image # if I print image, it is a pygame surface

    print background # But here, outside the loop, image is still a g_base instance ?!?!
    print mouse # " "   

main()

You can do:

imgs_to_load = [g_base("bg.jpg"), g_base("mouse.png",alpha=1)] # list with a g_base class instances

def Image_loader(img):
    # ..... code to load the image and convert it into pygame surface...
    return img_load

def main ():
    imgs_in_pygame_format = [] # create an empty list
    for image in imgs_to_load:
        loaded_image = Image_loader(image) 
        imgs_in_pygame_format.append(loaded_image) # add to the list 

    for image in imgs_in_pygame_format:
        print image # every image in the list is a pygame surface

    # or
    print image[0]
    print image[1]

main()

Or if you want to reference to images by name, you can put them into dictionary:

imgs_to_load = {} 
imgs_to_load["bg"] = g_base("bg.jpg")
imgs_to_load["mouse"] = g_base("mouse.png",alpha=1)

imgs_in_pygame_format = {} # create a global dictionary for loaded images

def main ():
    global imgs_in_pygame_format # import that global name into the local scope for write access
    for name, data in imgs_to_load.items():
        imgs_in_pygame_format[name] = Image_loader(data) # add to the dictionary

    for image in imgs_in_pygame_format:
        print image # every image in the dictionary is a pygame surface

    # or    
    print imgs_in_pygame_format["bg"]
    print imgs_in_pygame_format["mouse"]

main()

But most importantly, global variables are bad idea. The better solution would be to use a class:

def Image_loader(img):
    # ..... code to load the image and convert it into pygame surface...
    return img_load

class Image:
    def __init__(self, image):
        self.data = Image_loader(image)

def main ():
    bg = Image(g_base("bg.jpg"))
    mouse = Image(g_base("mouse.png",alpha=1))

    print bg.data
    print mouse.data

main()

For more examples see Python Tutorial.

Hope it helps, and welcome to StackOverflow!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...