【问题标题】:'self' parameter in Python non-class functionsPython非类函数中的'self'参数
【发布时间】:2016-09-22 23:48:00
【问题描述】:

我目前正在向一位热心的小学生教授一些基本的 Python,但我很难理解这段用于 etch-a-sketch 的代码中的一个奇怪的小异常。

# myEtchASketch application

from tkinter import *

#####Set variables
canvas_height = 400
canvas_width=600
canvas_colour="black"

p1_x=canvas_width/2
p1_y=canvas_height
p1_colour="blue"
line_width=6
line_length=9

####New window
window=Tk()
window.title("MyEtchASketch")
canvas=Canvas(bg=canvas_colour, height=canvas_height, width=canvas_width,highlightthickness=0)
canvas.pack()

##### Functions:

#player controls
def p1_move_N(self):
    global p1_y
    canvas.create_line(p1_x, p1_y, p1_x, (p1_y-line_length), width=line_width, fill=p1_colour)
    p1_y = p1_y - line_length

def p1_move_S(self):
    global p1_y
    canvas.create_line(p1_x, p1_y, p1_x, (p1_y+line_length), width=line_width, fill=p1_colour)
    p1_y=p1_y+line_length

def p1_move_W(self):
    global p1_x
    canvas.create_line(p1_x, p1_y, (p1_x-line_length), p1_y, width=line_width, fill=p1_colour)
    p1_x=p1_x-line_length

def p1_move_E(self):
    global p1_x
    canvas.create_line(p1_x, p1_y, (p1_x+line_length), p1_y, width=line_width, fill=p1_colour)
    p1_x=p1_x+line_length

def erase_all(self):
    canvas.delete(ALL)


#bind movement to key presses
window.bind("<Up>", p1_move_N)
window.bind("<Down>",p1_move_S)
window.bind("<Left>", p1_move_W)
window.bind("<Right>", p1_move_E)
window.bind("<u>", erase_all)

window.mainloop()

播放器控件是困扰我的地方。如果我没有添加self,代码将不起作用。我明白了:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\ThisIsNotMyRealUserFolder\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1550, in __call__
    return self.func(*args)
TypeError: p1_move_N() takes 0 positional arguments but 1 was given

我做了一些研究,发现self 用于类方法。如您所见,没有一个函数是类方法。我唯一能想到的是bind() 将传递给它的所有函数都视为类方法,这意味着它们需要self 才能正常工作。

感谢任何和所有的帮助。

【问题讨论】:

  • self 只是代表变量的名称。您可以将所有 self 更改为 x 并且它应该仍然有效。如果没有“self”,代码将无法工作,因为该方法仍然需要将 1 个参数传递给它(或者至少在它被调用时 - 它会传递 1 个变量)
  • 您已将参数称为self,但这只是一个名称。这里真正的问题是您不了解 tkinter 想要传递给您的回调的参数。 Go read about that.
  • @tehjoker: “Self 只是代表变量的名称。” - 不,它没有。它是对当前对象的引用,但前提是 this 是类中的方法(它不是)。
  • 如果你好奇,你可以print type(self) 在其中一个函数中。如果这里的人是正确的,它会说这是某种 TK Event 类。在这种情况下,您可能希望将self 重命名为evt 之类的名称,因为变量名称self 虽然对于Python 解释器是任意的,但对于Python 编码器来说不是任意的,并且在那里使用它会导致那种你刚刚经历的困惑。

标签: python class tkinter key-bindings


【解决方案1】:

传递给bind 的可调用对象接受一个参数:事件。因此,定义函数的正确方法是例如:

def p1_move_W(event):
    global p1_x
    canvas.create_line(p1_x, p1_y, (p1_x-line_length), p1_y, width=line_width, fill=p1_colour)
    p1_x=p1_x-line_length

Tk 将传递一个位置参数,因此您可以随意调用该参数(self 可以,是的,banana 也可以)。

另见the documentation for Tk event binding

【讨论】:

  • 我会说self 绝对行不通。从技术上讲,它是有效的,但名称非常具有误导性,导致代码难以理解和维护。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-14
  • 1970-01-01
  • 2012-04-21
相关资源
最近更新 更多