Python - Receiving more arguments than passing? - python

I'm learning python and gtk and so trying to using cairo to draw a rectangle in the screen with the mouse (I just managed to draw a rectangle without mouse).
However something strange is happening since I'm receiving more arguments than what I'm passing. How is that possible?
draw_rectangle - method definition:
def draw_rectangle (self, widget, start_x_cood, start_y_cood, ending_x_cood, ending_y_cood):
print ("draw_retangle")
cr = cairo.Context ()
cr.set_source_rgba(1, 1, 1, 1)
cr.rectangle(start_x_cood, start_y_cood, ending_x_cood, ending_y_cood)
cr.fill()
Method that calls draw_rectangle:
def on_motion_notify_event (self, widget, event):
print("on_motion_notify_event")
if event.is_hint:
x, y, state = event.window.get_pointer()
else:
x = event.x
y = event.y
state = event.state
if self.firstClick :
self.ending_x_cood = x
self.ending_y_cood = y
self.draw_rectangle(self, widget, self.start_x_cood, self.start_y_cood, self.ending_x_cood, self.ending_y_cood)
return True
This is giving me the following error:
on_motion_notify_event
Traceback (most recent call last):
File "gui2.py", line 56, in on_motion_notify_event
self.draw_rectangle(self, widget, self.start_x_cood, self.start_y_cood, self.ending_x_cood, self.ending_y_cood)
TypeError: draw_rectangle() takes exactly 6 arguments (7 given)
on_motion_notify_event
Traceback (most recent call last):
File "gui2.py", line 56, in on_motion_notify_event
self.draw_rectangle(self, widget, self.start_x_cood, self.start_y_cood, self.ending_x_cood, self.ending_y_cood)
TypeError: draw_rectangle() takes exactly 6 arguments (7 given)
Where is that 7th argument coming from?
My searches are leading me to *args and **kwargs but it's not making much sense.
I've uploaded a runnable version of the code here

Python passes self to instance methods for you, so:
self.draw_rectangle(self, widget, self.start_x_cood, self.start_y_cood, self.ending_x_cood, self.ending_y_cood)
actually is passing self twice. You want:
self.draw_rectangle(widget, self.start_x_cood, self.start_y_cood, self.ending_x_cood, self.ending_y_cood)

Related

Why is it in python so easy to overwrite a class method?

How can I protect in Python class methods from beeing mistakenly changed? Is there some kind of a "write protection"?
Example:
class bar():
def blob(self):
return 2
if __name__ == "__main__":
foo = bar()
print(foo.blob()) # Returns 2
foo.blob = 1 # Overwrites the method "blob" without a warning!
# foo.blob returns 1, foo.blob() is not callabele anymore :(
foo.blib = 1 # Is also possible
print(foo.blob)
print(foo.blob())
When I call this script returns:
2
1
Traceback (most recent call last):
File "blob.py", line 18, in <module>
print(foo.blob())
TypeError: 'int' object is not callable
I would prefer do get a warning.

What does the number following the argument represent?

I was wondering what the number following the argument stands for (In the error message; the number is 1).
I am updating PsychoPy, and it showed the error message. I have searched for a while, but I did not find any explanation about it.
def onCancel(self, event):
self.app.updater = None
self.Close()
def onFileBrowse(self, event):
self.filename = event.GetString()
def onInstall(self, event):
if self.currentSelection == self.useLatestBtn:
info = self.doAutoInstall()
else:
info = self.installZipFile(self.filename)
self.statusMessage.SetLabel(info)
self.Fit()
Traceback (most recent call last):
File "C:\Program Files (x86)\PsychoPy3\lib\site-
packages\psychopy\app\connections\updates.py", line 404, in onInstall
self.statusMessage.SetLabel(info)
TypeError: Control.SetLabel(): argument 1 has unexpected type 'int'
As #TomKarzes points out in the comments, it's just plain English: argument 1 is referring to the first argument. argument 2 would refer to the second argument and so on.

Calling methods from outside a class in Python - Tkinter events

I want to call a method in another class and make changes to the parent class when the button is clicked in Python. To explain; With Tkinter visual programming, I click the button to change the main window and I can not change the properties in the main window with another class method.
I get the error message below.
Exception in Tkinter callback Traceback (most recent call last):
File "/usr/lib/python3.5/tkinter/_ init _.py", line 1553, in _
call _
return self.func(*args) TypeError: buton_goster() missing 1 required positional argument: 'event'
class Butonol(object): #Button class
def __init__(self):
...
def buton_goster(self, event ): # Properties kisminda ozellik gosterir
Test.countshow = Test.countshow + 1;
if(Test.countshow >1):
Test.props0.pack_forget()
Test.props.pack_forget()
...
And here is the Test Class
class Test(Frame):
countshow = 0
...
def new_Button(self):
self.nesne = Butonol()
self.but= Button(self.mainFrame,text = self.nesne.text)
self.but.bind('<Button-1>',Butonol.buton_goster)
self.but.bind('B1-Motion>',self.label_tasi)
self.but.pack(side = LEFT,anchor = N)
Butonol.butonsay = Butonol.butonsay + 1
Butonol.butonliste.append(self.but)
The error is correct,
When you do you bind, you do not pass on the event, you simply add the function pointer.
If the buton_goster does not need "event" you should remove it or you should provide event as input when calling the function.

Tkinter error - Tuple index out of range

This program is supposed to put a sprite on the canvas for the user to control using the left and right arrow keys, but I keep getting a Tuple index out of range error, and I do not have any tuples in my program. I know that I properly imported the picture, so its probably something to do with the key pressing event.
#4/22/15
#Test game, user controlled sprite
import random
from Tkinter import *
import Tkinter
from PIL import Image, ImageTk
root = Tk()
root.geometry('700x600')
canvas = Canvas(root,width=700,height=600,bg='white')
canvas.place(x=0,y=0)
class Character_sprite(object):
'''Creates the users sprite and handles the events'''
def __init__(self):
self.im = Image.open('grey_mario_mushroom_sprite.png')
self.tkimage = ImageTk.PhotoImage(self.im)
self.char_sprite = canvas.create_image(image=self.tkimage)
def moveLeft(event):
'''Handles the left arrow key press event, moves char_sprite to the left'''
canvas.move(self.char_sprite,-20,0)
canvas.update()
def moveRight(event):
'''Handles the right arrow key press event, moves the char_sprite to the right'''
canvas.move(self.char_sprite,20,0)
canvas.update()
root.bind('<Left>', Character_sprite.moveLeft)
root.bind('<Right>', Character_sprite.moveRight)
Character_sprite()
root.mainloop()
This is the error:
Traceback (most recent call last):
File "C:\Users\Calvin\Documents\Python Programs\Test_game_example.py", line 57, in <module>
Character_sprite()
File "C:\Users\Calvin\Documents\Python Programs\Test_game_example.py", line 36, in __init__
self.char_sprite = canvas.create_image(image=self.tkimage)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 2310, in create_image
return self._create('image', args, kw)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 2294, in _create
cnf = args[-1]
IndexError: tuple index out of range
Please help!
The problem is that create_image requires a position. Like this:
self.char_sprite = canvas.create_image((0, 0), image=self.tkimage)
If Tkinter had been defined in a more friendly way, you'd get a friendlier error message:
>>> def create_image(position, **options):
... pass
>>> create_image(image=0)
TypeError: create_image() takes exactly 1 argument (0 given)
Unfortunately, Tkinter is often a bit complicated under the covers, so it's defined more like this:
>>> def create_image(*args, **options):
... position = args[-1]
... pass
So, you get a less useful error message. The *args ends up as an empty tuple, so that position = args[-1] raises an IndexError. And of course the variable isn't even called position, but cnf, which doesn't help you understand the problem.
But it's the same problem. You forgot to pass the position argument.

What do? __init__() takes exactly 3 arguments (1 given)? [duplicate]

This question already has an answer here:
__init__() takes exactly 3 arguments (1 given)
(1 answer)
Closed 8 years ago.
Here's the error it gives me along with the code lines specified. Apologies for past post.
Traceback (most recent call last):
File "H:\Users\Daniel\Desktop\Final Project\Gold Hunter.py", line 352, in <module>
main()
File "H:\Users\Daniel\Desktop\Final Project\Gold Hunter.py", line 346, in main
score = game()
File "H:\Users\Daniel\Desktop\Final Project\Gold Hunter.py", line 195, in game
pirate = Pirate()
TypeError: __init__() takes exactly 3 arguments (1 given)
ACTUAL CODE
main() Line 352
score = game() Line 346
pirate = Pirate() Line 195
Pirate Constructor It gives me the error NameError: global name 'dx' is not defined
class Pirate(pygame.sprite.Sprite):
EAST = 0
def __init__(self, screen, dx):
self.screen = screen
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("king_pirate/running e0000.bmp")
self.image = self.image.convert()
tranColor = self.image.get_at((1, 1))
self.image.set_colorkey(tranColor)
self.rect = self.image.get_rect()
self.rect.inflate_ip(-50, -30)
self.rect.center = (0, random.randrange(30,450))
self.img = []
self.loadPics()
self.frame = 0
self.delay = 4
self.pause = self.delay
self.dx = dx
I agree with Lee's comment. We cannot see the class Pirate: constructor but it is clear that your __init__ function is taking THREE arguments when you define it. These would be self, argument1, argument2, so when you call pirate = Pirate() on line 195, you must actually provide it 2 arguments (it will get self on its own). You need to give it the argument1 and argument2 that you defined in the constructor. Post the constructor for more help. Your line 195 should look something like pirate = Pirate(argument1, argument2)
Good Luck!

Categories

Resources