使用事件处理程序时如何更改全局变量

我是python的新手,从我十几岁起就对C ++有一定的经验,所以请保持冷静。

我想做的事情-左键单击添加一个点(到二维数组)并增加pointsCount变量。我正在像这样使用Tkinter绑定:

canvas.bind("<Button-1>",lambda event: leftClick(event,pointsCounter,points))

左键单击功能的定义如下:

def leftClick(event,numberOfPoints,pointsTable):
print("Left ",event.x," ",event.y)
x = roundup(event.x,50)
y = roundup(event.y,50)
pointsTable.append([x,y])
numberOfPoints = numberOfPoints + 1
print(pointsTable)
print(numberOfPoints)

虽然点的添加工作正常,但numberOfPoints仅在第一次单击后才增加。 我了解Python仅将一个值传递给该函数,因此我无法对其进行更改。但是它适用于数组。右键单击时,有什么方法可以增加numberOfPoints。

这是完整的代码

import array
import math
from tkinter import Canvas


def roundup(x,n=10):
    res = math.ceil(x/n)*n
    if (x%n < n/2)and (x%n>0):
        res-=n
    return res

def middleclick(event):
    print("Middle ",event.y)

def rightClick(event):
    print("Right ",event.y)
def leftClick(event,pointsTable):
    print("Left ",event.y)
    x = roundup(event.x,50)
    y = roundup(event.y,50)
    pointsTable.append([x,y])
    numberOfPoints = numberOfPoints + 1
    print(pointsTable)
    print(numberOfPoints)
    for i in range(1,5):
        canvas.create_oval(pointsTable[i][0] - radius,pointsTable[i][1] - radius,pointsTable[i][0] + radius,pointsTable[i][1] + radius,fill="red")
    return numberOfPoints

root = Tk()
canvas = Canvas(root,width = 800,height = 800)

radius = 5
points = [[]]
pointsCounter = 1



canvas.bind("<Button-1>",points))
canvas.bind("<Button-2>",middleclick)
canvas.bind("<Button-3>",rightClick)





canvas.pack()


root.mainloop()```


I'd be really grateful for some pointers. 


wangfei5131421 回答:使用事件处理程序时如何更改全局变量

pointsCount和pointsTable作为函数参数的区别在于pointsCount是不可变的,一旦更改,变量就会分配给新对象。 pointsTable是可变的,更改对象本身即会对其进行修改。也就是说,在函数中修改了pointsTable后,更改将反映在原始变量中。对于pointsCount,将创建一个值为pointsCount + 1的新对象,并在 inside 中指向pointCount。函数外部的pointsCount仍指向零对象。

一种解决方案是使pointsCount成为全局变量leftleft。另一种方法是根本不存储pointsCount,而是依靠pointsTable的长度(位于leftClick1下方)。

from random import randint

pointsTable = []
numberOfPoints = 0

class Event:  # Mock up to test code.
    def __init__(self):
        self.x = randint(0,50)
        self.y = randint(0,50)

# Keeping external counter
def leftClick(event,pointsTable):
    global numberOfPoints
    print("Left ",event.x," ",event.y)
    x = event.x
    y = event.y
    pointsTable.append([x,y])
    numberOfPoints = numberOfPoints + 1
    print(pointsTable)
    print(numberOfPoints)

def number_of_points(): 
# This may be overkill len(pointsTable) could be used instead
    return len(pointsTable)

# Using len(pointsTable)
def leftClick1(event,pointsTable):
    print("Left ",y])
    print(pointsTable)
    print(number_of_points())

for _ in range(2):
    leftClick( Event(),pointsTable )

for _ in range(2):
    leftClick1( Event(),pointsTable )

""" Output 
Left  5   4
[[5,4]]
1
Left  49   6
[[5,4],[49,6]]
2
Left  44   20
[[5,6],[44,20]]
3
Left  6   30
[[5,20],[6,30]]
4
"""

我会选择依靠pointsTable的长度来使其更简单,更强大

本文链接:https://www.f2er.com/3156021.html

大家都在问