Unresolved attribute reference '...' for class '...' - python

When I call the render() method in the Zombie class, I want to add an instance of the Zombie object into ZombieList.list. When I try to do this, it says
Unresolved attribute reference list for class ZombieList.
Should I try to do this another way?
class ZombieList:
def __init__(self):
self.list = []
for zombie in self.list:
ds.blit(zombie.image, (1000, random.randint(10, 790)))
class Zombie(object):
def __init__(self):
self.attack = 3
self.speed = 5
self.health = 30
self.image = pygame.image.load("Assets/green zombie.png")
self.zombieList = []
def render(self):
ZombieList.list.append(self)

You've to create a ZombieList object, where you can append the Zombie objects to.
You can add a Class Objects to to the class Zombie:
class Zombie(object):
zombies = ZombieList()
def __init__(self):
self.attack = 3
self.speed = 5
self.health = 30
self.image = pygame.image.load("Assets/green zombie.png")
def render(self):
Zombie.zombies.list.append(self)

You cannot append to a list of a class. You need to append to an instance of a class. For instance:
class ZombieList:
def __init__(self):
self.list = []
for zombie in self.list:
ds.blit(zombie.image, (1000, random.randint(10, 790)))
my_zombie_list = ZombieList() # create an instance
class Zombie(object):
def __init__(self):
self.attack = 3
self.speed = 5
self.health = 30
self.image = pygame.image.load("Assets/green zombie.png")
self.zombieList = []
def render(self):
my_zombie_list.list.append(self) # refer to the previously created instance

There is no attribute list in ZombieList. Only once you've created a ZombieList through e.g. self.zombie_list = ZombieList() will you be able to make use of your list through self.zombie_list.list.
Even then, though, I imagine this probably isn't the design you're aiming for: I imagine that you don't want a ZombieList for each individual Zombie. Rather, whoever is initializing the Zombie objects should probably be in charge of maintaining the ZombieList instance as well.
You will also run into other issues. For example, the loop in
self.list = []
for zombie in self.list:
ds.blit(zombie.image, (1000, random.randint(10, 790)))
will never have any effect since self.list is always empty when that code is executed (since you've defined it to be empty on the previous line).

Related

How to import a class and tap into its __init__ attributes without initialising it in python?

I am trying to add some futures to my snake game. What I want to do is every third point that the snake eats, there is a mega point and its value is 3 instead of 1.
from turtle import Turtle
import random
class Food(Turtle):
def __init__(self):
super().__init__()
self.shape("square")
self.penup()
self.shapesize(stretch_len=0.5, stretch_wid=0.5)
self.color("#C9C9C9")
self.speed(10)
self.refresh()
def refresh(self):
random_x = random.randint(-280, 280)
random_y = random.randint(-280, 265)
self.goto(random_x, random_y)
from turtle import Turtle
ALIGNMENT = 'center'
FONT = ('Courier', 22, 'normal')
class Scoreboard(Turtle):
def __init__(self):
super().__init__()
self.score = 0
with open('data.txt') as data: # open and reading a file
self.high_score = int(data.read())
self.color('white')
self.penup()
self.goto(x=0, y=270)
self.hideturtle()
self.update_scoreboard()
def update_scoreboard(self):
self.clear()
self.write(f"Score: {self.score} High score: {self.high_score}", align=ALIGNMENT, font=FONT)
def reset(self):
if self.score > self.high_score:
self.high_score = self.score
with open('data.txt', mode='w') as data: # writing to a file
data.write(f"{self.high_score}")
self.score = 0
self.update_scoreboard()
def increase_score(self):
if self.score % 5 == 0:
self.score += 3
else:
self.score += 1
self.update_scoreboard()
What I thought is to use the modulo% in the scoreboard.py to increase the score attribute by 3 points every third food spawn, and I have managed to do that, the problem is, I do not know how to either tap into the scoreboard score attribute and change the color of the food in relation to the score without having two overlayed scoreboards on screen, or create some kind of loop in food.py that achieves the same functionality by looping through a list of colors.
I've also tried this method answered by another person on here but I couldn't make it work.
import inspect
params = []
for parent in ExampleParams.mro()[::-1]:
parent_init = inspect.getfullargspec(parent.__init__)
# parent_init.annotations contains annotations if specified in method signature
for param in parent_init.args:
if param == 'self':
continue
params.append(param)

How can I call a class method on an instance within a different class __init__

I am creating a tic-tac-toe game in python. I'm trying to call the update method from my Board class on my boardState object within the class init of my Turn class.
When I run it I get NameError: name boardState is not defined.
class Board:
def __init__(self, player1 = "player1", player2 = "player2"):
self.p1 = player1
self.p2 = player2
self.matrix = MATRIX
self.winner = 'none'
self.available = getAvailable(self.matrix)
def update(self):
clear()
getAvailable(self.matrix)
self.show()
class Turn:
def __init__(self, sym):
self.sym = sym
boardState.update()
terminalState(boardState, self.sym, available)
print(f"{self.sym}'s turn:")
def main():
boardState = Board()
altTurns()
you are getting this error siense you haven't defined "boardState" before referencing it,
you need to set it to be a new Board Object before using it
class Board:
def __init__(self, player1 = "player1", player2 = "player2"):
self.p1 = player1
self.p2 = player2
self.matrix = MATRIX
self.winner = 'none'
self.available = getAvailable(self.matrix)
def update(self):
clear()
getAvailable(self.matrix)
self.show()
class Turn:
def __init__(self, sym):
self.sym = sym
boardState = Board() #the line I added
boardState.update()
terminalState(boardState, self.sym, available)
print(f"{self.sym}'s turn:")
this should fix your problem
If you want your Turn object to have access to the boardState object you've created in main() (and for main in turn to have access to the updated boardState), you should pass it in as a parameter to give all of the relevant functions access to it.
I assume the Turn is created by altTurns, so altTurns should itself take a board object that it can use to create the initial Turn.
class Turn:
def __init__(self, sym, boardState):
self.sym = sym
boardState.update()
terminalState(boardState, self.sym, available)
print(f"{self.sym}'s turn:")
def altTurns(boardState):
sym = None # or something?
turn = Turn(sym, boardState)
# more turns happen?
def main():
boardState = Board()
altTurns(boardState)
# our boardState has now been updated by Turn()

why can't I call my method from within class in python?

I am trying to make a button class for my game, using pygame. But in the button class, I cannot call methods that are contained in the class itself.
I am new to classes so I may be missing something important, I'm sorry
I tried to add self to the isHovering() Method but it still doesn't work.
import pygame
class Button():
def __init__(self, pos, value, img, screen):
self.pos = pos
self.value = value
self.img = img
self.screen = screen
### Getters and Setters ###===============
### Get/Set Value : True/False ###
def setValue(self, value):
self.value = value
def getValue(self):
return self.value
### Get/Set Pos ###
def setPos(self, pos):
self.pos = pos
def getPos(self):
return self.pos
### Get/Set Img ###
def setImg(self, img):
self.img = img
def getImg(self):
return self.img
#==========================================
def isHovering(self):
pos = getPos()
imgRect = pygame.rect(pos[0], pos[1], 105, 105)
if imgRect.collidepoint(pygame.mouse.get_pos()):
return True
else:
return False
def update(self, screen):
if isHovering():
image = pygame.transform.scale(self.img(95, 95))
else:
image = pygame.transform.scale(self.img(105, 105))
screen.blit(image, self.pos)
I thought that when update(screen) was called in my main loop, that it would call isHovering(), and return a True or False, but instead I get this error:
NameError: name 'isHovering' is not defined
In def update(self, screen),
The if statement should be if self.isHovering().
If not, the interpreter will look for a isHovering function somewhere in the current module, like if you had defined it outside your class.
Using the self. prefix will indicate that you are indeed trying to call a method of the instance as JacoblRR already pointed out in a comment.

Kivy: How to automate clock processes one after the other

Was writing a tetris game and have come across some challenges which seem insurmountable. I would like the blocks to fall one after the other systematically but can't seem to get it as i come across one error after the other. This is my the error serving code
#All modules have been imported
class block1(Widget):
def __init__(self, **kwargs):
super(block1, self).__init__(**kwargs)
xpositions = (0, 50, 100, 150, 200, 250, 300, 350, 400)
self.bind(pos= self.fall)
self.pos_x = random.choice(xpositions)
self.pos_y = Window.height
self.pos = (self.pos_x,self.pos_y)
self.vel_x = 0
self.vel_y = -5
velocity = vel_x,vel_y
def fall(self, **kwargs):
self.pos = Vector(*self.position) + self.pos
if self.pos[1]==0:
self.position[1] = 0
return self.pos
#classmethod
def new_widget(cls):
return cls
#This widget is intended to help me create the new instance of a the
same class i.e to multiply this block within my app
class block2(Widget):
def __init__(self, **kwargs):
super(block1, self).__init__(**kwargs)
xpositions = (0, 50, 100, 150, 200, 250, 300, 350, 400)
self.bind(pos= self.fall)
self.pos_x = random.choice(xpositions)
self.pos_y = Window.height
self.pos = (self.pos_x,self.pos_y)
self.vel_x = 0
self.vel_y = -5
velocity = vel_x,vel_y
def fall(self, **kwargs):
self.pos = Vector(*self.position) + self.pos
if self.pos[1]==0:
self.position[1] = 0
return self.pos
#classmethod
def new_widget(cls):
return cls
#This widget is intended to help me create the new instance of a the
same class i.e to multiply this block within my app
I am facing three problems. The first is from my function under my block class call fall I keep getting an error that says block1 has no attribute called velocity when it is clearly in my __init__ function.
I defined two new block classes customized the .kv files for each, defining different colors and sizes for each. I made my code to define a new startup position and a fixed velocity whenever the class was created. After this I then created the fall class to make my application fall.
In the build of my app class i tried to make the blocks fall one after the other by detecting when one has fallen and making the next begin then.
def build(self):
game= board()
first = block1()
second = block2()
game.add_widget(first)
Clock.schedule_interval(first.fall, 1/60)
if first.pos[1] == 0:
game.add_widget(second)
Clock.schedule_interval(second.fall, 1/60)
Secondly in my init function i tried to bind the fall function to the pos property of the class so as the block falls, the pos property of the class changes with it. Regardless the program doesn't seem to detect the change in the pos regardless of the bind.
Lastly I tried to create a new #classmethod that would help me create new blocks repeatedly and infinitely for the tetris app and dont know where i got it wrong. I created a class method that returns a new instance of the class and planned on creating a loop that keeps creating a new instance of a class in this way:
game = tetrisgame()#This is the main layout for the game
while game:#To create a loop to keep adding new blocks
blockchoice = randint(1,6)
if blockchoice == 1:
game.add_widget(block1.new_widget)
Clock.schedule_interval(block1.fall,1/60)
for i in allblocks:
if block1.collide_widget(i):
block1.position[1] = 0
This gives me a bind error saying widget.bind error, and fails to create a new instance for my class.
Could someone help me clarify?
Note: I tried to pick out the parts of the code that were the source of the error to prevent having a post with a lengthy amount of code, so please note that all modules have been imported and the .kv files with all the designs are omitted.
Lots of problems here. Your block1 indeed does not have a velocity attribute. The velocity mentioned in your __init__() is only a local variable. If you want it to be an attribute, you must assign it as self.velocity=. Also the reference to velx,vely does not reference the attributes self.velx and self.vely.
Your fall() method references a self.position that I do not see defined anywhere.
I don't see how your widget position is being changed. Perhaps that line in your fall() method should be: self.pos = Vector(*self.velocity) + self.pos.
The pos attribute of the Widget tells Kivy where to draw it, so I don't think you worry about binding pos to anything, it will be the position of the Widget.

How update variable within another class

I have these classes :
class Game():
def __init__(self):
self.player = Player("name")
class Turn():
def __init__(self):
pass
def end(self):
#how update xp player
class Player():
def __init__(self, name):
self.name = name
self.xp = 0
And my question is how when turn is terminated, how update the player
If these classes are in the same module you can define a global variable in the module that can be used in both classes. Otherwise you need to explicitly pass the variable on the instances of both classes.
Your Game class appears to have a reference to a player in its self.player attribute. If you want to update that player's xp attribute, you can do something like this:
def end(self):
self.player.xp += 5

Categories