我是python中的新手,我在使用global
指令时遇到了很多麻烦
这是一个代码示例:
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"
这就是问题所在。我该如何解决?
答案 0 :(得分:6)
你的问题是Python的工作方式与你的想法不同 因此,我将尝试逐行解释代码中发生的情况。
mouse = "a"
将字符串“a”分配给名称mouse
。
background = "b"
将字符串“b”指定给名称background
。
list_ab = [mouse, background]
将名称mouse
和background
引用的两个对象分配到列表list_ab
。
我们已经知道,它们是常数“a”和“b”。所以你可以写:
list_ab = ["a", "b"]
现在循环
for item in list_ab:
将列表中的每个对象分配给名称item
对于第一次循环迭代,它意味着item = "a"
。
该行
global item # I want to modify the GLOBAL item, which is mouse ad background
没有意义,因为它试图告诉Python名称item
是全局的,而没有声明这样的全局变量。
对于线上最令人困惑的行为
item = "modified"
你应该明白,虽然它将字符串“modified”分配给名称item
,但字符串“a”和“b”仍然相同,仍然分配给列表list_ab
(以及您未触及的mouse
和background
名称。
名称item
本身仅存在于声明的范围内,当“for”循环结束时,它被破坏。
它还会在每次迭代时使用list_ab
中的下一项重新分配。
总结一下:
如果要将“已修改”字符串分配给列表中的项目,请直接执行:
list_ab[0] = "modified"
list_ab[1] = "modified"
如果需要更改全局范围内声明的变量,请执行以下操作:
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"
基于问题第一次修订的示例:
而不是
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()
你可以这样做:
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()
或者,如果您想按名称引用图像,可以将它们放入字典中:
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()
但最重要的是,全局变量是个坏主意。更好的解决方案是使用类:
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()
有关更多示例,请参阅Python Tutorial。
希望它有所帮助,欢迎来到StackOverflow!
答案 1 :(得分:4)
正如我在对您的问题的评论中所说,list_ab
不包含对mouse
和background
的引用。在这种情况下,您可以通过将名称放在列表中来模拟,如下所示:
mouse = "a"
background = "b"
list_ab = ['mouse', 'background']
def func():
for name in list_ab:
globals()[name] = "modified"
print mouse # must be "modified" not "a"
print background # must be "modified" not "b"
func()
# modified
# modified
globals()
返回一个类似字典的对象,表示脚本/模块执行中该点的非本地名称绑定。重要的是要注意list_ab
中的for
循环不会更改func()
。此外,您应该知道,这只是一个简单的方法,可以让您的示例代码按照您的需要运行,而不是通过特别好或通用的方式来完成这些事情。
答案 2 :(得分:2)
我不确定你在做什么。 global
关键字旨在将全局名称导入当前范围,而不是将本地名称全局化。
答案 3 :(得分:2)
你有两个不同的问题,其中一个出现两次。首先,您试图在列表的元素上使用global
,这是无用的。你已经可以了:
def func():
list_ab[0] = 'modified'
list_ab[1] = 'modified'
这将更改list_ab
引用的值,这比您的代码现在得到的值更远。它的工作原理是因为您没有更改list_ab
表示的绑定,因此它不需要是全局的。您已经可以读取全局索引,并且它只是一个项目查找,并且(本身)不会覆盖任何绑定。但是,它实际上不会更改a
和b
第二个是当你将list_ab
的第一个和第二个索引绑定到a
和b
时,它会创建全新的绑定,以便更改列表中绑定的值不会更改a
和b
引用的值。如果你想这样做,你需要直接这样做。
def func():
global a, b
a = 'modified'
b = 'modified'
当您尝试通过迭代修改list_ab
的元素时,您再次遇到第二个问题。您可以使用代码
def func():
list_ab = ['a', 'b']
for item in list_ab:
item = 'modified'
print list_ab # prints ['a', 'b']
同样,这是因为您正在创建对该值的新绑定,然后修改该绑定而不是原始绑定。
如果您需要在迭代时修改列表,可以执行
def func():
list_ab = ['a', 'b']
for i in xrange(len(list_ab)):
list_ab[i] = 'modified'
因此,目前更新a
,b
和list_ab
以及保持当前模式(即不引入理解),您需要执行以下操作:
def func():
global a, b
for i in xrange(len(list_ab)):
list_ab[i] = 'modified'
a = 'modified'
b = 'modified'
print list_ab
print a, b
看起来很难看。为什么需要将它们作为自由变量保存在列表中?这不仅仅是一个足够好的清单吗?如果您需要通过名称访问它们,那么您可以使用字典:
dict_ab = {'a': 'a', 'b': 'b'}
for key in dict_ab:
dict_ab[key] = modified
print dict_ab['a']
print dict_ab['b']
答案 4 :(得分:1)
这里的问题是您尝试就地更新变量,但您的函数会返回新实例。尝试这样的事情:
def main ():
converted_images = []
for image in [mouse, background]:
converted_images.append(Image_loader(img))
# now re-assign the pygame surfaces to the old names
background, mouse = converted_images
如果你想要特别简洁,这里有一个同样的事情:
background, mouse = [Image_loader(img) for img in [background, mouse]]
但实际上,如果你只有两张图片,那么明确地做这件事会更有意义:
background = Image_loader(background)
mouse = Image_loader(mouse)
答案 5 :(得分:0)
我不确定你要做什么,但这是使用global
的一个例子:
value = 7
def display():
print value # global values are read-only any time
def increment():
global value # must declare global to write it
value += 1
def local():
value = 9 # this is a local value
print value
increment() # changes global value to 8
display() # displays it
local() # changes local value to 9 and displays it
print value # displays global value (still 8)