I'm having trouble with inheritance between classes. The class I'm struggling with is the vulture class which is a subclass of the bird class which is a subclass of the critter class. The bird and critter class, and the main that they're being run through, all work fine. But when I try to use the vulture class, I get an error:
AttributeError: 'Vulture' object has no attribute '_Bird__direction'
I'm not sure what I did wrong, and I'm hoping someone could help me find my mistake.
Vulture class:
from bird import *
class Vulture (Bird):
def __init__(self):
self.__hungry=True
self.__in_a_row=-1
self.__direction=DIRECTION_NORTH
def eat(self):
if self.__hungry:
self.__hungry=False
return True
else:
return False
def fight(self, opponent):
self.__hungry=True
return super(Bird, self).fight(self,opponent)
def get_color(self):
black
Bird class:
from Critter import *
class Bird (Critter):
def __init__(self):
self.__in_a_row=-1 #doesn't go north 3 times on first move if set to 0
self.__direction=DIRECTION_NORTH
def fight(self, opponent):
if opponent.__str__=="%": #roars at ants
return ATTACK_ROAR
else:
return ATTACK_POUNCE
def get_color(self):
return "blue"
def __str__(self): #uses the most recent direction to determine which character should be used
if (self.__direction==DIRECTION_NORTH or self.__direction==DIRECTION_CENTER):
return "^"
elif self.__direction==DIRECTION_EAST:
return ">"
elif self.__direction==DIRECTION_SOUTH:
return "V"
else:
return "<"
def get_move(self):
if self.__in_a_row<2:
self.__in_a_row+=1
return self.__direction
else: #Turning in the proper direction after it hits the end of the line
if self.__direction==DIRECTION_NORTH:
self.__direction=DIRECTION_EAST
self.__in_a_row=0
return self.__direction
elif self.__direction==DIRECTION_EAST:
self.__direction=DIRECTION_SOUTH
self.__in_a_row=0
return self.__direction
elif self.__direction==DIRECTION_SOUTH:
self.__direction=DIRECTION_WEST
self.__in_a_row=0
return self.__direction
elif self.__direction==DIRECTION_WEST:
self.__direction=DIRECTION_NORTH
self.__in_a_row=0
return self.__direction
def eat(self):
return False
I don't think that the critter class itself will be relevant in this, and it's pretty big, so I'll leave that off the post unless someone thinks it might help to have.
See this section on Private Variables in the Python documentation.
Python treats instance variables that start with double-underscores specially, mangling the name to keep them private to the class (even private from the parent class). When you call a Bird method on your Vulture class, the Bird method references to self.__direction are actually referencing the self._Bird__direction variable which is distinct from the self._Vulture__direction variable that you initialize in your Vulture __init__ constructor.
In particular:
v = Vulture() # initializes self._Vulture__direction only
print(v) # throws an exception -- v._Bird__direction isn't initialized
Edit: As #ShadowRanger points out, the convention in Python is to prefix with a single underscore those instance variables or methods that are intended to be private to the implementation but freely shared between superclasses and subclasses (i.e., similar to protected in Java or C++). There's no special treatment of such variables by the language, it's just a signal to users of the class that they shouldn't "mess" with those instance variables or methods.
This is probably what you intended for __direction, __in_a_row, and maybe even __hungry (though that last one doesn't appear in the Bird class). If you change all these double underscore prefixes to single underscores, that should clear up your problem.
Related
Say I have a Word class with subclasses ShortWord and LongWord. Is there a way to dynamically determine which subclass gets instantiated based on a given input? I mean I could define a separate function like
def instantiate(text):
if len(text) < 5:
return ShortWord(text)
else:
return LongWord(text)
But that doesn't feel very (for lack of a better word) elegant. Is there a good way to go about this? I have found some similar questions in other languages, but nothing python-specific.
I would define a #staticmethod in the base class which makes the determination.
You might need to define a __init_subclass__ in the base class to at least be aware of what classes are there, since you don't know about the subclasses before the base class is defined.
class Word(object):
_tr = {} # Type registry
#staticmethod
def instantiate(text):
if len(text) < 5:
cls = __class__._tr.get('ShortWord')
else:
cls = __class__._tr.get('LongWord')
return cls(text) if cls is not None else None
def __init_subclass__(cls):
__class__._tr[cls.__name__] = cls
class ShortWord(Word):
pass
class LongWord(Word):
pass
I thought it over after seeing the comments, and this is another approach. Didn't want to submit two answers for one question. UPDATE: Thanks to #chepner's comment, I cleaned it up further.
class Word(object):
#staticmethod
def instantiate(text):
if len(text) < 5:
return ShortWord(text)
else:
return LongWord(text)
class ShortWord(Word):
pass
class LongWord(Word):
pass
Instantiate with val = Word.instantiate(text)
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.
I'm adapting the text adventure game tutorial, github, to fit python 2.7. I'm using the PyCharm 4.5.4 community edition for my IDE. When I don't override a parent method it gives me an error:
Class WolfRoom must implement all abstract methods
At first to get rid of this error I defined the missing method def modify_player(self, the_player): as pass but I quickly realized I was overriding the method with nothing which isn't what I wanted. Now if I just remove the method from the WolfRoom class I get an IDE error, as seen above, but it appears to work just fine when I run my game. Should I leave this method out or define it and use super()?
Here are some code snippets:
class MapTile(object):
"""The base class for all Map Tiles"""
def __init__(self, x, y):
"""Creates a new tile.
Attributes:
:param x: The x coordinate of the tile.
:param y: The y coordinate of the tile.
"""
self.x = x
self.y = y
def intro_text(self):
"""Information to be displayed when the player moves into this tile."""
raise NotImplementedError()
def modify_player(self, the_player):
"""Process actions that change the state of the player."""
raise NotImplementedError()
def adjacent_moves(self):
"""Returns all move actions for adjacent tiles."""
moves = []
if world.tile_exists(self.x + 1, self.y):
moves.append(actions.MoveEast())
if world.tile_exists(self.x - 1, self.y):
moves.append(actions.MoveWest())
if world.tile_exists(self.x, self.y - 1):
moves.append(actions.MoveNorth())
if world.tile_exists(self.x, self.y + 1):
moves.append(actions.MoveSouth())
return moves
def available_actions(self):
"""Returns all of the available actions in this room"""
moves = self.adjacent_moves()
moves.append(actions.ViewInventory())
return moves
...
class EnemyRoom(MapTile):
def __init__(self, x, y, enemy):
self.enemy = enemy
super(EnemyRoom, self).__init__(x, y)
def intro_text(self):
pass
def modify_player(self, the_player):
if self.enemy.is_alive():
the_player.hp = the_player.hp - self.enemy.damage
print("Enemy does {} damage. You have {} HP remaining.".format(self.enemy.damage, the_player.hp))
def available_actions(self):
if self.enemy.is_alive():
return [actions.Flee(tile=self), actions.Attack(enemy=self.enemy)]
else:
return self.adjacent_moves()
...
class WolfRoom(EnemyRoom):
def __init__(self, x, y):
super(WolfRoom, self).__init__(x, y, enemies.Wolf())
def intro_text(self):
if self.enemy.is_alive():
return """
A grey wolf blocks your path. His lips curl to expose canines as white as
the nights sky. He crouches and prepares to lunge.
"""
else:
return"""
The corpse of a grey wolf lays rotting on the ground.
"""
I believe this is actually due to the PyCharm inspector making an error, or at least a dubious decision regarding PEP 8 style, when looking to see if there are any non-implemented methods which will raise a NotImplementedError. Consider this simpler example which is very similar:
class Base(object):
def foo(self):
raise NotImplementedError
def bar(self):
return 0
class Child(Base):
def foo(self):
return 0
class GrandChild(Child):
def bar(self):
return 1
my_grand_child = GrandChild()
print my_grand_child.foo()
The above code successfully prints a 0 to the output, because when Python can't find the implementation of foo() in GrandChild it looks up the inheritance chain and finds it in Child. However, for some reason the PyCharm inspector expects all classes which raise NotImplementedError to be implemented in ALL levels of the inheritance chain.
If you were to follow this style in programs with large inheritance structures, you would find yourself being extremely verbose by implementing methods and making calls to super all throughout the chain, when it simply isn't required. Personally, I just ignore the error, and think that PyCharm should be updated to not show it if it finds the method implemented in any superclass of the class it is inspecting.
Simply raising NotImplementedError from a method doesn't quite make it an abstract method. You can still instantiate a class that doesn't override all its inherited pseudo-abstract methods, you just can't call the methods. (Or rather, you can even call them, if you catch the NotImplementedError in a try statement.)
You can use abc.ABCMeta to make a class truly abstract; the metaclass machinery prevents you from even instantiating a class with an un-overriden abstract method.
import abc
class MapTile(object):
"""The base class for all Map Tiles"""
__metadata__ = abc.ABCMeta
def __init__(self, x, y):
"""Creates a new tile.
Attributes:
:param x: The x coordinate of the tile.
:param y: The y coordinate of the tile.
"""
self.x = x
self.y = y
#abc.abstractmethod
def intro_text(self):
"""Information to be displayed when the player moves into this tile."""
pass
# etc.
Yes, you have to implement all abstract methods in Python to instantiate them as objects (the ones marked with #abstractmethod, etc). How you implement these, however, are completely up to you. If you're not going to be instantiating, you don't need to override all of them.
For example:
class Animal(object):
__metaclass__ = ABCMeta
#abstractmethod
def eat(thing):
pass
class Slug(Animal):
def eat(thing):
pass
What this means is that every instantiatable Animal must be able to eat, but Slugs do nothing when they eat.
A beginner level question.. trying to understand how I can best use the built-in unittest. In the trivial example below, the method consume_food picks a food item and then I am calling food.cut() method.
In future, this method may return instance of Drink object. The #commented code indicates one possible future implementation. In this case, self.milk will not have the cut method defined.
I want to add a unit test for consume_food and pick_food methods. I would like to do this for the original implementation first and then change it after adding self.milk functionality.
EDIT: The intention is to write a unit test for an existing api, so that I can capture any such changes ( i.e. absence of Drink.cut method) forcing me to update the methods and unit tests.
Can someone please help showing me how to write a unit test for this example?
class Fruit:
def cut(self):
print("cut the fruit")
class Drink:
def pour(self):
print("pour the drink")
class A:
def __init__(self):
self.apple = Fruit()
self.banana=Fruit()
#self.milk = Drink()
#self.liquid_diet = True
def consume_food(self):
food = pick_food()
food.cut()
print("consuming the food")
def pick_food(self):
return self.apple
#if self.liquid_diet: return self.milk
#return self.apple
The thing is, your cut() and consume_food() methods don't really do much right now that allow you to make meaningful assertions after you execute them in a test.
So I'd suggest to expand your initial code a little bit to have those methods act upon the respective objects so that you can make meaningful assertions on their state after invoking those methods.
Right now, all they really do is write to STDOUT, which is sort of a global state - which should generally be avoided and is always difficult to test. (I'm not saying that printing output is a bad thing - but if that's the only thing your code does, it's going to be very tricky to test).
So I introduced a common superclass Food which has a consume() method, and sets a corresponding attribute. Similarly, the cut() method on Fruit now sets an attribute that you can test for.
import unittest
class Food(object):
def __init__(self):
self.consumed = False
def consume(self):
self.consumed = True
class Fruit(Food):
def __init__(self):
super(Fruit, self).__init__()
self.been_cut = False
def cut(self):
print("cut the fruit")
self.been_cut = True
class Consumer(object):
def __init__(self):
self.apple = Fruit()
self.banana = Fruit()
def consume_food(self):
food = self.pick_food()
food.cut()
print("consuming the food")
food.consume()
def pick_food(self):
return self.apple
These tests now can make assertions on the object's states after the relevant methods have been invoked. Note that they follow the AAA pattern - Arrange Act Assert:
First, you arrange the objects under test the way you need them (instantiate a consumer).
Then you act on the objects under test (invoking the method in question)
Finally, you make assertions on the resulting state you expect the objects to be in
class TestConsumer(unittest.TestCase):
def test_consume_food_consumes_the_apple(self):
c = Consumer()
c.consume_food()
self.assertTrue(c.apple.consumed,
"Expected apple to be consumed")
def test_consume_food_cuts_the_food(self):
c = Consumer()
c.consume_food()
self.assertTrue(c.apple.been_cut,
"Expected apple to be cut")
def test_pick_food_always_selects_the_apple(self):
c = Consumer()
food = c.pick_food()
self.assertEquals(c.apple, food,
"Expected apple to have been picked")
if __name__ == '__main__':
unittest.main()
My question deals with creating a tick procedure the original tick procedure where it makes a class called PoliceOfficer arrest everyone who is naked around him.
def tick(self):
# next time step for all objects that tick
for t in self.__things:
obj = self.get_thing(t)
if has_method(obj, "tick"):
obj.tick()
This the original tick method.
This is my PoliceOfficer class and the method known as arrest. The arrest method arrests someone based upon them not having any clothes on when in the area of the PoliceOfficer, and when there isn't anyone to arrest he just says something else.
class PoliceOfficer (Person):
def __init__(self, name, jail):
Person.__init__(self, name)
self.set_restlessness(0.5)
self.__jail = jail
def arrest (self, Person):
if self.location.name is Person.location.name:
self.say (Person.name + "You're under arrest!")
self.say ("You have the right to shut up and lay on the ground with your hands behind your back")
Person.name(Place("jail")
else:
return self.say (Person.name + "Ain't got nothing to do damnit")
def tick (self):
if isinstance(t, Student):
if Student.is_dressed = False:
arrest.student
else:
(Person)tick(): self.say("Shoot no one to arrest off to the 7 eleven")
Would this be partially correct on making my own tick method for PoliceOfficer?
If not what else would I need to do or change to make it like the tick method described, except for making the PoliceOfficer arrest any student that isn't dressed?
Uhm,... you want to test is an object is of a certain class? Python has a built-in function for that: isinstance(). Quick example:
>>> isinstance(1, int)
True
>>> isinstance("Hello World!", int)
False
>>> isinstance("Hello World!", str)
True
Check the documentation for more information.
http://docs.python.org/library/functions.html#isinstance
As per delnan's "suggestion", a little piece of advice: instead of checking for the class behind the Person you receive, it's cleaner to have Person implement a canBeArrested() method that subclasses can override, for which Student can return false.
class Person(object):
(...)
def canBeArrested(self):
return True
class Diplomat(Person):
(...)
def canBeArrested(self):
# Overrides Person's default behaviour
return False
There are two ways:
obj.__class__.__name__ == "Student"
or
isinstance(obj, Student)
I recommend the second way, but sometimes you really need the name of the class, for which obj.__class__.__name__ is the way to go.