2016-09-22 37 views
-2

我目前正在向渴望小學的學生講授一些基本的Python,並且在這段代碼中遇到了一些奇怪的小異常,蝕刻-A-草圖。Python中的'self'參數非類函數

# 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才能正常工作。

任何和所有的幫助表示讚賞。

+0

自我僅表示變量的名稱。你可以將所有selfs改爲x,它仍然可以工作。如果沒有「self」,代碼就無法工作,因爲該方法仍然需要傳遞1個參數(或至少當它被調用時 - 它傳遞1個變量) – AK47

+2

您已經調用了參數'self',但它只是一個名字。這裏真正的問題是你不明白tkinter想要傳遞給你的回調的參數。 [去看看這個。](http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm) – user2357112

+0

@tehjoker:_「自我只是表示變量的名稱。」_ - 不,它確實不。它是對當前對象的引用,但前提是這是一個類中的方法(事實並非如此)。 –

回答

0

傳遞給bind的可傳回參數有一個參數:event。因此,要定義函數的正確方法是例如:

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

+0

我會說「自我」絕對不行。從技術上講,它是有效的,但名稱是非常具有誤導性的,導致難以理解和維護的代碼。 –