I made classes for what will basically become a BreakOut game, but I keep getting error messages. The nature of which always seem to surround two things; Class imports and the infamous "super" method. Usually in the form of a syntax error
I had some questions shot down in the past, so I will try to be as clear as I possibly can.
The main code for the game is as such...
import pygame
from Game import *
from Game.Scenes import *
from Game.Shared import *
class BreakOut:
def __init__(self):
self.__lives = 5
self.__score = 0
self.__level = Level(self)
self.__level.load(0)
self.__pad = Pad((0,0), 0)
self.__balls = [Ball((0,0), 0, self)]
pygame.init()
pygame.mixer.init()
pygame.display.set_caption("This is the Title of the Game")
self.__clock= pygame.time.Clock()
self.screen = pygame.display.set_mode(GameConstants.SCREEN_SIZE, pygame.DOUBLEBUF, 32)
pygame.mouse.set_visible(0)
self.__scenes = (
PlayingGameScene(self),
GameOver(self),
HighScoreScene(self),
MenuScene(self)
)
self.__currentScene = 0
self.__sounds = ()
def start(self):
while 1:
self.__clock.tick(100)
self.screen.fill((0,0,0))
currentScene = self.__scenes[self.__currentScene]
currentScene.handleEvents(pygame.event.get())
currentScene.render()
pygame.display.update()
def changeScene(self, scene):
pass
def getLevel(self):
pass
def getScore(self):
pass
def increaseScore(self, score):
pass
def getLives(self):
pass
def getBalls(self):
pass
def getPad(self):
pass
def playSound(self, soundClip):
pass
def reduceLives(self):
pass
def increaseLives(self):
pass
def reset (self):
pass
BreakOut().start()
At this stage, its only supposed to return a black screen, but instead it keeps giving me a error message with this traceback:
Traceback (most recent call last):
File "/Users/Ryan/PycharmProjects/Demo 1/Game/BreakOut.py", line 3, in <module>
from Game import *
File "/Users/Ryan/PycharmProjects/Demo 1/Game/__init__.py", line 9, in <module>
from Game.BreakOut import BreakOut
File "/Users/Ryan/PycharmProjects/Demo 1/Game/BreakOut.py", line 4, in <module>
from Game.Scenes import *
File "/Users/Ryan/PycharmProjects/Demo 1/Game/Scenes/__init__.py", line 3, in <module>
from Game.Scenes.HighScoreScene import HighScoreScene
File "/Users/Ryan/PycharmProjects/Demo 1/Game/Scenes/HighScoreScene.py", line 7
SyntaxError: invalid syntax
The bottom one connects to another class of code that looks like this:
from Game.Scenes.Scene import Scene
class HighScoreScene(Scene):
def __init__(self, game):
super(HighScoreScene, self.__init__(game)
PyCharm seems to highlight "super" and tells me "Old-style class contains call for super method" I don't know if that's important or not, but its something I've noticed consistently throughout the code.
I'm pretty sure its a simple mistake. Might be a typo, but I can't pinpoint it for the life of me. Please help!
super(HighScoreScene, self.__init__(game) # <- missing paren
It should be super(HighScoreScene, self).__init__(game)
And use object class BreakOut(object) if you want to use super.
New-style and classic classes
Your class Breakout line is not in line with the rest of your program (ahead by one space). If you backspace that line by one, everything should be fine (including #Padraic Cunningham 's answer).
Related
I am trying to build snake from turtles but am running into an attribute error when using the .xcor(), .ycor(), .pos() functions from the turtle class. Basically anything that returns a value from the turtle class is not working in my program. Here is my code:
from turtle import Turtle, Screen
import time
import random
screen = Screen()
class Snake(Turtle) : ## create snake class and pass Turtle class into it
def __init__(self):
self.xcors = []
self.ycors = []
self.snakesegs = []
self.create_snake()
def create_snake(self):
N = 0
for segs in range(1,4):
super().__init__(shape="square")
self.color("black")
self.penup()
self.goto(N,0)
self.snakesegs.append(super().__init__)
N -= 20
xcor = super().__init__.xcor()
ycor = super().__init__.ycor()
self.xcors.append(xcor)
self.ycors.append(ycor)
and here is the traceback I am getting:
Traceback (most recent call last):
File "/Users/gcinco/Documents/Python/Jett-Black/SNAKE/snake.py", line 49, in <module>
snape = Snake()
File "/Users/gcinco/Documents/Python/Jett-Black/SNAKE/snake.py", line 13, in __init__
self.create_snake()
File "/Users/gcinco/Documents/Python/Jett-Black/SNAKE/snake.py", line 24, in create_snake
xcor = super().__init__.xcor()
AttributeError: 'function' object has no attribute 'xcor'
If anyone has any idea what is going on please help, thanks!
You are calling superclass's constructor when calling super().__init__().
if you are trying to to call super's methods, just do
xcor = super().xcor()
ycor = super().ycor()
super().__init__ is the initialization method of class Turtle. It has no xcor or ycor attribute. I think what you intend is to call the x|y cor methods on the segment you created, which is much simpler:
segment = super().__init__(shape="square")
self.xcors.append(segment.xcor())
self.ycors.append(segment.ycor())
You might have an even easier time with simply:
self.segments = [super().__init__(shape="square") for _ in range(4)]
Then loop through the segments to set the desired characteristics of each:
self.color("black")
for square in self.segments:
# draw each segment in turn
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.
I'm sending a variable value from programa1 for a new object using :
def send_price(self):
self.pricesend = float(self.text1.get()) #this take a value from a tkinker.Entry
print(self.pricesend)
objetoprograma1.Object(self.pricesend)
the object "objetoprograma1" return a new value using:
class Object():
def __init__(self, price):
self.price_recibe = float(price)
print(self.price_recibe)
self.new_price = self.price_recibe + 10
print(self.new_price)
programa1.Aplication.recibe_newprice(self, float(self.new_price))
now I want to update the value in the principal1 tkinter.Entry called self.text1:
def recibe_newprice(self, new_price):
self.new_price = new_price
print("price new recibe" , self.new_price)
## this don't work.. this don't update or change the value in the tkinter.Entry
self.text1.delete(0, len(self.text1.get()))
self.text1.insert(self.my_main, str(self.new_price))
I have the following exception:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1482, in __call__
return self.func(*args)
File "B:\MAESTRIA\PYTHON\trabajos\hello\programa1.py", line 38, in send_price
objetoprograma1.Object(self.pricesend)
File "B:\MAESTRIA\PYTHON\trabajos\hello\objetoprograma1.py", line 19, in __init__
programa1.Aplication.recibe_newprice(self, float(self.new_price))
File "B:\MAESTRIA\PYTHON\trabajos\hello\programa1.py", line 51, in recibe_newprice
self.text1.delete(self.my_main, len(self.text1.get()))
AttributeError: 'Object' object has no attribute 'text1'
the full programa1.py
# -*- coding: latin-1 -*-
import tkinter
import objetoprograma1
import time
class Aplication():
def __init__(self,my_main):
self.my_main = my_main
self.variables()
self.GUI()
def variables (self):
self.price = None
self.list = []
def GUI(self):
self.text1 = tkinter.Entry()
self.text1.insert(0, "1000")
self.text1.grid(column = 0, row = 0)
self.boton1 = tkinter.Button(self.my_main, text = "sendprice", command = self.send_price )
self.boton1.grid(column=1, row = 0)
def send_price(self):
self.pricesend = float(self.text1.get())
print(self.pricesend)
objetoprograma1.Object(self.pricesend)
def recibe_newprice(self, new_price):
self.new_price = new_price
print("price new recibe" , self.new_price)
## this don't work
self.text1.delete(0, len(self.text1.get()))
self.text1.insert(self.my_main, str(self.new_price))
if __name__ == "__main__":
root = tkinter.Tk()
#root.geometry("800x500+0+0")
root.title("titulo")
app = Aplication(my_main=root)
root.mainloop()
and objetoprograma1.py
# -*- coding: latin-1 -*-
import programa1
import tkinter
import time
class Object():
def __init__(self, price):
self.price_recibe = float(price)
print(self.price_recibe)
self.new_price = self.price_recibe + 10
print(self.new_price)
programa1.Aplication.recibe_newprice(self, float(self.new_price))
Look at your Object class and look at the exception message. You are calling the recibe_newprice method, but passing it the Object instance (Object has no text1 attribute). The recibe_newprice is written for the Aplication class and as such expects self to be an instance of the Aplication class. You seem to be mixing up what classes are for or how the self argument works.
My first tip is to name things with more descriptive names. Names like Object, Application, and Program1 don't tell the reader anything about what the purpose of those objects are.
Second, do you know the difference between classes and functions? Maybe this will help. I would code the send_price method this way:
def send_price(self, price_recibe):
pricesend = float(self.text1.get())
print(pricesend)
print(price_recibe)
new_price = price_recibe + 10
print(new_price)
self.recibe_newprice(new_price)
If this doesn't make sense why I'm doing things this way or why this might be considered better/easier than the way you did it then I suggest researching how python classes, attribute assignment, and argument passing works.
In Python, can a constructor take in a method of another class as an argument?
I've heard that you can do something like this, but this example isn't working (currently, I'm getting a 'module' object is not callable error):
class GeneticAlgorithm ():
def __init__(self, population, fitness, breed, retain = .3, weak_retain = .15 ) :
self.fitness = fitness
Here fitness is a function defined elsewhere and note that I am importing the class where the function is defined.
edit: Here's the code that actually produces the error
class Solver( ):
def __init__( self, fitness, breed, iterations ):
self.T = Problem()
self.fitness = fitness
self.breed = breed
self.iterations = iterations
def solve( self ):
P = self.T.population(500)
GA = GeneticAlgorithm(P, self.fitness, self.breed) # problem here
Traceback (most recent call last):
File "C:\Users\danisg\Desktop\Other\Problem.py", line 128, in <module>
main()
File "C:\Users\danisg\Desktop\Other\Problem.py", line 124, in main
t = S.solve()
File "C:\Users\danisg\Desktop\Other\Problem.py", line 74, in solve
GA = GeneticAlgorithm(P, self.fitness, self.breed)
TypeError: 'module' object is not callable
And where the Solver is created
def main():
S = Solver(fitness, breed, 35)
print(S.solve())
if __name__ == '__main__':
main()
From the comments, the root of the issue:
I do `import GeneticAlgorithm'. I should not do this? – gjdanis
No, that's not actually correct. What you've done is import the module, not the class that's inside the module. You have two options here - do one or the other:
Change the import to
from GeneticAlgorithm import GeneticAlgorithm
Change the Solver class to use
GA = GeneticAlgorithm.GeneticAlgorithm(P, self.fitness, self.breed)
I'd suggest renaming the module from GeneticAlgorithm.py to something that isn't quite as confusing (genetic_algorithm.py is a good candidate), then using the first option to import just the class from that module - from genetic_algorithm import GeneticAlgorithm
Yes, you could have something like this:
def eats_a_method(the_method):
pass
def another_method():
pass
eats_a_method(another_method)
Take a look at the stack trace:
GA = GeneticAlgorithm(P, self.fitness, self.breed)
TypeError: 'module' object is not callable
It says GeneticAlgorithm is a module, not a function.
I am new in Python and I wrote the following code:
class Frazione:
def __init__(self, Numeratore, Denominatore=1):
mcd=MCD(Numeratore,Denominatore)
self.Numeratore=Numeratore/mcd
self.Denominatore=Denominatore/mcd
def MCD(m,n):
if m%n==0:
return n
else:
return MCD(n,m%n)
def __str__(self):
return "%d/%d" %(self.Numeratore, self.Denominatore)
def __mul__(self, AltraFrazione):
if type(AltraFrazione)==type(5):
AltraFrazione=Frazione(AltraFrazione)
return Frazione(self.Numeratore*AltraFrazione.Numeratore, self.Denominatore*AltraFrazione.Denominatore)
__rmul__=__mul__
Open shell at the same folder of Frazione.py:
>>> from Frazione import Frazione
end then
>>> f=Frazione(10,5)
When I press Enter, I receive this output:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File ".\Frazione.py", line 5, in __init__
mcd=MCD(Numeratore,Denominatore)
NameError: global name 'MCD' is not defined
PS. I apologize for my english!
MCD is a method of Frazione, but you're calling it as if it were a global function. The easiest (and cleanest, IMHO) fix is to just move it outside the class, because it doesn't need to access any class or instance members.
So:
def MCD(m, n):
if m % n == 0:
return n
else:
return MCD(n, m % n)
class Frazione:
# as before but without MCD
If you do want to keep it in the class, then you might rewrite it to be iterative instead of recursive and call it as self.MCD in __init__. That's a good idea anyway, as Python's support for recursion is rather weak.