I have just started an exercise where I am supposed to complete a basic 'angrybirds' clone.
I am stuck at the point where I want to remove an object from a list. The list contains all of the obstacles used in-game (boxes).
So if I want to remove a box after it was hit I have to make a method to do that. This fails no matter how I do it.
class spel(object):
def __init__(self):
self.obstacles = [obstacle(50,pos=(200,90)),]
#defines all other stuff of the game
class obstacle(object):
def __init__(self,size,pos):
#defines how it looks like
def break(self):
#methode that defines what happens when the obstacles gets destroyed
spel.obstacles.remove(self)
The error I get is:
AttributeError: 'NoneType' object has no attribute 'obstacles'
After the last line.
Please excuse me for my noob-level, but the point is that I won't ever have to code again after this, so there is no need to explain everything.
You have defined 'spel' as a class, not an object. Thus, you have received an error because Python is trying to find a member 'obstacles' of the spel class, which doesn't exist before the __init__ method of individual spel objects is run.
To associate an object of the spel class with each individual obstacle you create, you could try giving objects of the obstacle class a data member that refers to their associated spel object. The data member can be instantiated in the obstacle class' __init__ function. Like this:
class obstacle(object):
def __init__(self, spel, size, pos):
self.spel = spel
#etc
def break(self):
self.spel.obstacles.remove(self)
Hope that helps.
You haven't instantiated the spel class.
If you want to use a class like that, you have to intantiate( create an instance of) it.
Outside of a class like so:
app = spel() # app is an arbitrary name, could be anything
then you would call it's method like this:
app.obstacles.remove(self)
Or in you're case, from within another class:
self.spel = spel()
self.spel.obstacles.remove(self)
I propose the following:
class spel(object):
obstacles = []
def __init__(self,size,pos):
spel.obstacles.append(obstacle(size,pos))
#defines all other stuff of the game
class obstacle(object):
def __init__(self,size,pos):
self.size = size
self.pos = pos
def brak(self):
#methode that defines what happens when the obstacles gets destroyed
spel.obstacles.remove(self)
from pprint import pprint
a = spel(50,(200,90))
pprint( spel.obstacles)
print
b = spel(5,(10,20))
pprint( spel.obstacles )
print
c = spel(3,None)
pprint( spel.obstacles )
print
spel.obstacles[0].brak()
pprint( spel.obstacles )
return
[<__main__.obstacle object at 0x011E0A30>]
[<__main__.obstacle object at 0x011E0A30>,
<__main__.obstacle object at 0x011E0B30>]
[<__main__.obstacle object at 0x011E0A30>,
<__main__.obstacle object at 0x011E0B30>,
<__main__.obstacle object at 0x011E0AF0>]
[<__main__.obstacle object at 0x011E0B30>,
<__main__.obstacle object at 0x011E0AF0>]
Related
I am new to python ( started 1 week ago) and this is the first time i am doing coding so i am not able to understand fairly simple things as well.
can you explain this function to to me? i understand that a function is being defined with 2 input required self and my_object, but what is happening next? please explain like you would to a newbie.
class chain():
def __init__(self, my_object):
self.o = my_object
def __getattr__(self, attr):
x = getattr(self.o, attr)
if hasattr(x, '__call__'):
method = x
return lambda *args: self if method(*args) is None else method(*args)
else:
prop = x
return prop
Firstly, chain is not a Function, it's a Class.
A class in simple words is a definition of an object. (say Car)
Now the __init__ function of the class simply defines what's "in it" meaning what variables or properties does it has. Say for example a class Car:
class Car:
def __init__(self,maxspeed,color):
self.speed = maxspeed #So what's defined under **__init__** is a property of a class.
self.color = color
So here Class car has speed and color as variables(or attributes or properties)
Now there are methods , of simply function that control the behaviour of the object and it's functionalities.
class Car:
def __init__(self,maxspeed,color):
self.speed = maxspeed #So what's defined under **__init__** is a property of a class.
self.color = color
def accelarate(self): #Method to increase the speed of car object.
self.sepped = self.speed + 10
Now the method you have is a magical one , __getattr__
Say a scenario where you want to acess the brand of the car , now you haven't define self.brand in it's __init__ function so you you'll get an error when you call it like:
>>>red_car = Car(100,red) #Creating an object named red_car of class Car
>>>red_car.color
>>>'red'
>>>red_car.brand
>>> Attribute Error , Class car dosen't has attribute brand
Now remove this error when calling an undefined property for a object or put simple we tell tell the class what to do if an undefined variable is called we use the method __getattr__.
class Dummy(object):
def __getattr__(self, attr):
return attr.upper()
d = Dummy()
d.does_not_exist # 'DOES_NOT_EXIST'
d.what_about_this_one # 'WHAT_ABOUT_THIS_ONE'
In the above code does_not_exist property (attribute) is NOT define but still we are not getting error as the getattr catches it and does as instructed. In this case it catches attr capitalises it and returns it rather than throwing an error in your face.
The class chain has a constructor that takes an argument my_object and assigns it to an instance variable self.o.
The method __getattr__ is a special magic method that has been overridden to delegate calls to the initial my_object variable we first received.
The result of the delegated call is checked for a method named __call__. If present, it is called and the returned value is returned. If not, the value itself is returned as-is.
What is going on. I have looked at other solutions on stack overflow but non seem to work from what I have seen. I have a base object with a method that changes the value of the base attribute. When I call the base function in a child class (Inheritance) I get that the child class does not have the attribute "baseAttribute"
class GameObject(object):
#This is the base class for gameObjects
def __init__(self):
self.components = {}
def addComponent(self, comp):
self.components[0] = comp #ignore the index. Placed 0 just for illustration
class Circle(GameObject):
#circle game object
def __init__(self):
super(GameObject,self).__init__()
#PROBLEM STATEMENT
self.addComponent(AComponentObject())
#or super(GameObject,self).addComponent(self,AComponentObject())
#or GameObject.addComponent(self, AComponentObject())
EDIT:
Apologies, I never originally passed in a self.
Simple - leave out the second self:
self.addComponent(AComponentObject())
You see, the above actually translates to
addComponent(self, AComponentObject())
In other words: in essence "OO" works on functions that have an implicit this/self pointer (however you name that) as argument.
You are using incorrect arguments for .addComponent() method.
# ...
class Circle(GameObject):
def __init__(self):
super(GameObject,self).__init__()
# NOT A PROBLEM STATEMENT ANYMORE
self.addComponent(AComponentObject())
# ...
Here is a class that assigns a symbol to a player. It should accept a move and add the move to the existing repository of moves of the player.
class Player:
...: positions = []
...: def __init__(self,symbol):
...: self.symbol = symbol
...: def move(self,position):
...: self.position = position
...: self.positions.append(self.position)
My problem is that positions is behaving "globally" in the sense that it is not tied to an object instance, to demonstrate:
>>>a = Player('x')
>>>b = Player('y')
>>>a.move(1)
>>>b.positions
[1]
When you say,
class Player:
positions = []
positions will be a class variable and the same object is used by all the instances of the class. You can confirm by this
player1, player2 = Player(), Player()
print player1.positions is player2.positions # True
print Player.positions is player1.positions # True
If you want to create instance variables (separate positions variable for each and every instance of Player), you can create that in __init__ function. It is a special initializer function, which gets the current actual object as the first parameter. You can create positions variable and attach it to that object like this
class Player:
def __init__(self):
self.positions = []
player1, player2 = Player(), Player()
print player1.positions is player2.positions # False
Here, self refers to the newly constructed object and you are creating a new variable in that object by self.positions and you are initializing it with an empty list by
self.positions = []
So, whenever you create a new instances of Player, self will refer to the new instance created and new variable positions will be created on every instance, which means separate positions variable for each and every instance.
And whenever move is called, you don't have to create a new position variable on self. Instead you can do this
def move(self, position):
self.positions.append(position)
If you are using Python 2.x, its better to use new style classes, like this
class Player(object):
def __init__(self):
self.positions = []
Declare it inside the __init__ method. Anyhting declared outside the __init__ method will be a class attribute and will be shared between all instances of the class.
You don't have to pass it anything:
class Player:
...: def __init__(self,symbol):
...: self.symbol = symbol
self.positions = []
...: def move(self,position):
...: self.position = position
...: self.positions.append(self.position)
Yes you need to make class variable into instance variable, which will bind only to a particular instance.
Currently, positions = [] is class variable which can access from all the instances. So, you better assign to a particular instance variable.
You can do that by define inside __init__(), which will call when you create an instance of that class.
IMO you'd also want to initialize self.position to None in init, lest you hit this error:
p = Player()
p.position
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: Player instance has no attribute 'position'
So you'd want this:
class Player(object): # making it a new-style class
def __init__(self, ...):
...
self.position = None
My problem is that positions is behaving "globally" in the sense that it is not tied to an object instance, to demonstrate
Yes, that is by design of the language. Python follows a rule that is not like some other modern languages with OO support, but is very simple and easily understood: everything you write inside the class block describes a part of the class. (Remember, in Python, everything is an object - including the classes themselves.)
So I do not really understand what the problem is. You clearly already know how to make things that belong to the instances (hint: you are already doing it with symbol). You may just need to re-think your design and be clearer about what you intend to happen.
I have a library of component objects. I would like to include instantiations of a selection of those objects in another object. But I would like to provide that selection as a list so that each time I instantiate the container object with a list, it will be created with the specified sub objects in it.
Let's say my component library looks like this:
class ColorBlob(object):
...
def wipeItUp()
...
class RedBlob(ColorBlob):
...
def paintIt()
...
class YellowBlob(ColorBlob):
...
def paintIt()
...
class BlueBlob(ColorBlob):
...
def paintIt()
...
And my container object looks like this:
class Pallet(object):
def __init__(self, colorList):
for color in colorList:
#Ok, here is where I get lost if I know the color I can do this:
Pallet.BlueBlob = blobLib.BlueBlob()
#But I don't, so I am trying to do something like this:
blobSpecs = getattr(blobLib, color)
blobSpecs.Obj = blobSpecs().returnObj(self.page) # with "returnObj" defined in the library as some other method
setattr(self, Pallet.blobName, blobSpecs) #and I am completely lost.
But what I really want to do in my functional code is this:
workingPallet=Pallet(['RedBlob', 'BlueBlob'])
workingPallet.RedBlob.paintIt()
I know that I am lost when I try to instantiate the sub objects in the container. Can someone help me straighten out my "getattr" and "setattr" nonsense?
You were almost there, but it isn't your getattr or setattr that's the problem. You end up setting the class back on self, not the instance you created:
def __init__(self, colorList):
for color in colorList:
blobSpec = getattr(blobLib, color)
blob = blobSpec() # create an instance of the blob
blob.Obj = blob.returnObj(self.page)
setattr(self, color, blob)
It's the same thing as calling the class directly (BlueBlob()), but now through a variable.
I'm new to python, and it really confused me.
I want to write something like
class line :
points = []
def add(self, point) :
self.points.append(point)
line1 = line()
line2 = line()
line1.add("Some point")
print line2.points
Output: ['Some point']
And the result is like they refers to the same list.
But I do want a object member not a class member.
And I tried, if points is int, or some other simple type it works fine.
Besides, I know if I write
def __init__(self) :
self.points = []
it will also work, but I don't get why they are pointing to same list by default.
ps. I know writing a init will work.
class line :
name = "abc"
def changename(self, name) :
self.name = name
line1 = line()
line2 = line()
line1.changename(123)
print line2.name
But the code above output "abc"
So I don't understand why same kind of declaration act different by type.
Because in this case
class line :
points = []
points is a class member. It belongs to the class, and since line1 and line2 are of the same class, points is the same list.
So you are right in using
def __init__(self) :
self.points = []
instead to create an instance member which is tied to the instance, not the class.
To answer your edit
If you write:
def changename(self, name) :
self.name = name
you override your class member and create a new instance member using self.name = name.
To get back to your first example, it would be like writing:
def add(self, point) :
self.points = self.points + [point]
The first syntax:
class line :
points = []
makes points a class attribute. Therefore, it will be shared between all instances of the class.
To make sure that an attribute belongs to a class, you should do as follows:
class line(object) :
def __init__(self):
self.points = []
i.e., creating the attributed only in __init__, when a new instance is created.
As others have already explained, and as you apparently already understand, the following creates a class attribute, shared by every instance:
class line:
points = []
When you reference this attribute in your code, Python attempts to find it the current scope, and then follows the enclosing scopes. So if you call self.points.append(), you are indeed changing the points class attribute.
When you assign to self.points in your code, you are defining a new points instance attribute. So in your second example when points is a string, the changename function actually creates a new instance attribute when called.
You can try the following:
print line.name # prints the class attribute
print line1.name # prints the class attribute
print line2.name # prints the instance attribute
You will notice that calling changename did create a new instance attribute, while the class attribute is left unchanged. As changename was never called on line1, a reference to its name will resolve to the line class attribute.