python namerror name is not defined - python

I am having trouble figuring out why I am getting this error . My code is this
#define the Animal Class
class Animal:
def __init__ (self, animal_type, age, color):
self.animal_type = animal_type
self.age = age
self.color = color
def makeNoise():
pass
def __str__(self):
print ("% is % years old and is %" % animal_type,age, color)
#define child classes of Animal
class Wolves(Animal):
def __init__(self, animal_type, age, color, wild):
Animal.__init__(self, animal_type, age, color)
self.wild = wild
def __str__(self):
print ("% is % years old and is % and is %" % (animal_type, age, color, wild))
class Bear(Animal):
def __init__ (self, animal_type, age, color, sex):
self.sex = sex
Animal.__init__(self,animal_type, age, color)
class Moose(Animal):
def __init__(self, animal_type, age, color, antlers):
self.antlers = antlers
Animal.__init__(self, animal_type, age, color)
#add items to each class
wally = Wolves("wolf", 4, "grey","wild")
sally = Wolves("wolf", 3, "white", "tame")
print (str(sally))
print (str(wally))
and the full trace-back is
Traceback (most recent call last):
File "//mgroupnet.com/RedirectedFolders/SBT/Documents/bear51.py", line 41, in <module>
print (str(sally))
File "//mgroupnet.com/RedirectedFolders/SBT/Documents/bear51.py", line 24, in __str__
print ("% is % years old and is % and is %" % (animal_type, age, color, wild))
NameError: name 'animal_type' is not defined
What am I doing wrong?

Oh - well basically you just forgot to use self.animal_type in your __str__ method. Like so:
def __str__(self):
print ("%s is %s years old and is %s" % self.animal_type,self.age, self.color)
Just like in __init__, to use variables from your instantiated class, you need to use "self", as in "from this animal instance that I'm working on".

In Python methods are just normal functions. Therefore, you cannot access a local variable from one method in another method. The typical way to share information between methods is via self. To get animal_type in __str__, you need use self.animal_type. There is no special name space for methods in a class. This means in terms of visibility of names it does not matter if you write functions in a module or methods in a class.

In Python, self is not a keyword like this in Java. It is just a parameter like any other, which, by convention, is usually called self.
When you call a method, like some_animal.__str__()1, this is actually just syntactic sugar for Animal.__str__(some_animal), where some_animal is bound to the self parameter.
Thus, in Java (and many other languages) this means "look at the current instance for this attribute" and is optional, when unambiguous (i.e. when there is no local variable of the same name), but Python's self is not optional. It's just a regular method parameter.
1 __str__ is not a good example, as you never call it in this way, but rather str(some_animal), but you know what I mean

Related

What is the purpose of the last two lines of code

I am trying to characterise my class with init but the website says I have to add the last two lines of code but I don't know what they do? Could someone explain?
Code:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def myfunc(self):
print("My awesome name is " + self.name)
p1 = Person("bob", 69)
p1.myfunc()
It is pretty simple. Let's say you create a string.
a = "Hello"
This basically creates a new string object called a. Now you can use a variety of functions like .isdigit(), .isalnum() etc. These functions are basically the functions of the String class and when called, they perform the function in relation to the object they are associated with.
So Saying,
print(a.isalnum())
Would give True as the function is defined to check of the String object is alphanumeric.
In the same way,
p1 = Person("bob", 69)
p1.myfunc()
First-line creates a new Person object with name='bob' and age=69. The second line then calls the function myfunc() in association with the Person p1 and executes with the attributes of p1 as its own local variables.
The first chunk of code is defining a class. This says what the class should be called, what attributes it has, and defines its behaviour.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def myfunc(self):
print("My awesome name is " + self.name)
Once those lines are run, the class exists in your session, but no instances of it do.
This creates an instance of the class:
p1 = Person("bob", 69)
And this line is that instance calling its method myfunc():
p1.myfunc()

How can I make the OOP code print my classes objects name?

I've tried to make an OOP based program in python. I gave it an object to work with and tried to make it print the name, but its not working.
class human:
def __init__(self, name):
print("this is a human")
def name(self, name):
print("this is {}".format(bob.name))
bob = human("bob")
Anyone know what the problem could be?
Beyond the answers you already received (which solve your problem), I'd suggest not having a method that prints the name. Rather, you should have a __str___ dunder method that defines the object's behavior when an instance is printed.
class human:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
person = human("bob")
print(person)
'bob'
You can also define the object's behavior when the instance name is entered in the console, for instance just running the line
>>> person
You can do it with __repr__:
def __repr__(self):
return f'when entering the instance name in the console: {self.name}'
This will print:
when entering the instance name in the console: bob
This appears more pythonic to me than having a method that simply prints the name.
You're never storing the name on the instance, where would it get the name from? Your __init__ needs to do something along the lines of self.name = name
the name method and attribute are going to conflict, the latter will shadow (hide) the former, and it should look up whatever attribute its using on self
You never assigned the passed name to the object. Try:
class human:
def __init__(self, name):
print("this is a human")
self.name = name
def print_name(self):
print("this is {}".format(self.name))
bob = human("bob")
bob.print_name()
there are couple of things to update in the code:
bob is an instance which is not defined at human class
notice that init, name functions expect external param but you never use it in the function. (in self. = name)
in order to use it:
define a var in the class named 'name' and update you function to:
class human:
_name = ""
def __init__(self, name):
print("this is a human")
self._name = name
def name(self):
print("this is "+ self._name)
bob = human("bob")
bob.name()
bob = human("bob") only init function and you should call bob.name() in order to call the print-name function

unbound method error - Text Based Adventure

I am creating a text based adventure in python. I have ready two books on python and taken an online course, so I think I really have all the basics down.
Now I am creating my items currently. My setup is
Item->Weapon->(specific weapon here).
All classes inherit the previous.
I am unable to print the values of the items such as Holy_Sword and Stick. I am able to print them if I don't create them as classes and just use a variable to create the instance of weapon. However, due to what I want to do further down the line, I really would like them to be classes.
The error I am getting is:
unbound method str() must be called with Holy_Sword instance as first argument (got nothing instead)
My code is:
class Item(object):
def __init__(self, name, value, description):
self.name = name
self.value = value
self.description = description
def item_description(self):
return "Your %s is worth %d gold and is a %s" % (self.name, self.value, self.description)
class Weapon(Item):
def __init__(self,name, value,description, attack):
self.attack = attack
super(Weapon, self).__init__(name, value, description)
def __str__(self):
return "Your %s is worth %d gold and has an Attack Damage of %d, it is %s" % (self.name, self.value, self.attack, self.description)
class Stick(Weapon):
def __init__(self, name, value, description, attack):
super(Stick, self).__init__(name = "Stick", value= 1, description = "A stick...there may be potential here....or not.", attack = 1)
class Holy_Sword(Weapon):
def __init__(self, name, value, description, attack):
super(Holy_Sword, self).__init__(name = "The Holy Sword of Antioch", value= 20, description = "A Sword whose potential far outweighs it's lack of stylishness ", attack = 20)
class Sword(Weapon):
def __init__(self, name, value, description, attack):
super(Sword, self).__init__(name = "Sword", value= 3, description = "A Wooden Sword.", attack = 5)
print Holy_Sword.__str__()
Keep in mind that, in the code you have here, Holy_Sword refers to a class. It is not itself an instance of Item.
Holy_Sword.__str__ is an instance method. It can't be called on its own like you're trying to do here; it must be called through an instance of the Holy_Sword class.
(Note that it's usually better to not invoke __str__ directly. This method should usually only be called through the str() function, e.g. str(Holy_Sword).)
What you can do is create an instance of Holy_Sword and print the string value of that:
sword = Holy_Sword()
print str(sword)
However, you may want to instead consider making Holy_Sword be a instance of Weapon with specific attributes, rather than being a subclass. If the only way it needs to differ from other weapons is in its attributes, there's no need for it to be a separate class.
You need to instantiate the class first:
my_sword = Holy_sword(...)
print my_sword.__str__()

Inheritance in python, Attribute error [duplicate]

This question already has answers here:
What is the meaning of single and double underscore before an object name?
(18 answers)
Closed 6 years ago.
I have recently started learning python and i am having a hard time how inheritance works in python.
I have created two classes, one is named Animal and another one is named Dog. Dog class inherits Animal class. I have some attributes like name, height, sound etc in Animal class which i want to use in Dog class. I am setting the attributes using init method of Animal class.
class Animal:
__name = ""
__height = 0
__weight = 0
__sound = 0
def __init__(self, name, height, weight, sound):
self.__name = name
self.__height = height
self.__wight = weight
self.__sound = sound
def set_name(self, name):
self.__name = name
def get_name(self):
return self.__name
def set_height(self, height):
self.__height = height
def get_height(self):
return self.__height
def set_weight(self, weight):
self.__weight = weight
def get_weight(self):
return self.__weight
def set_sound(self, sound):
self.__sound = sound
def get_sound(self):
return self.__sound
def get_type(self):
print("Animal")
def tostring(self):
return "{} is {} cm tall and {} kilograms and says {}".format(self.__name,
self.__height,
self.__weight,
self.__sound)
cat = Animal("whiskers", 50, 20, "meow")
print(cat.tostring())
class Dog(Animal):
__owner = None
def __init__(self, name, height, weight, sound, owner):
super(Dog, self).__init__(name, height, weight, sound)
self.__owner = owner
def set_owner(self, owner):
self.__owner = owner
def get_owner(self):
return self.__owner
def get_type(self):
print("dog")
def tostring(self):
return '{} is {} cm tall and {} kilograms and says {} His owner is {}'.format(self.__name,
self.__height,
self.__weight,
self.__sound,
self.__owner)
def multiple_sounds(self, how_many=None):
if how_many is None:
print(self.get_sound())
else:
print(self.get_sound() * how_many)
my_dog = Dog("spot", 50, 40, "Ruff", "Derek")
print(my_dog.tostring())
Problem is when i try to print all the attributes using object of Dog class, an error is displayed saying "
*line 73, in tostring
return '{} is {} cm tall and {} kilograms and says {} His owner is {}'.format(self.__name,
AttributeError: 'Dog' object has no attribute '_Dog__name'*
Can anyone help me find the problem in this code ?
Members which start with double underscore are sort of private, so they are not accessible from cild classes. You should use single underscore. Python does not use implicit access specifiers like c++ or java but instead a special name convention is used: names with _ prefix are for protected and names with __ are for private. Also python does not check that you don't violate that convention, it is considered a bad practice to access protected or private methods outside of the class. If you start a name with double underscore it is mangled in a special way. So __name actually becomes _Animal__name when you use it in an Animal class and _Dog__name when you use it in a Dog.
The problem is the double underscore prefixes in your names. They trigger name mangling.
You should avoid using these. They don't do what you expect.
Using double underscores in Python makes a variable "private". Its similar to using the private keyword in other languages. You need to remove them if you want to access the attributes outside of the parent class.
The Python documentation touches on this subject:
Since there is a valid use-case for class-private members (namely to avoid name clashes of names with names defined by subclasses), there is limited support for such a mechanism, called name mangling. Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class. (emphasis mine)

__init__ and the setting of class variables

Im having some trouble understanding Inheritance in classes and wondering why this bit of python code is not working, can anyone walk me through what is going wrong here?
## Animal is-a object
class Animal(object):
def __init__(self, name, sound):
self.implimented = False
self.name = name
self.sound = sound
def speak(self):
if self.implimented == True:
print "Sound: ", self.sound
def animal_name(self):
if self.implimented == True:
print "Name: ", self.name
## Dog is-a Animal
class Dog(Animal):
def __init__(self):
self.implimented = True
name = "Dog"
sound = "Woof"
mark = Dog(Animal)
mark.animal_name()
mark.speak()
This is the output through the terminal
Traceback (most recent call last):
File "/private/var/folders/nd/4r8kqczj19j1yk8n59f1pmp80000gn/T/Cleanup At Startup/ex41-376235301.968.py", line 26, in <module>
mark = Dog(Animal)
TypeError: __init__() takes exactly 1 argument (2 given)
logout
I was trying to get animal to check if an animal was implemented, and then if so, get the classes inheriting from animal to set the variables that Animals would then be able to manipulate.
katrielalex answered your question pretty well, but I'd also like to point out that your classes are somewhat poorly - if not incorrectly - coded. There seems to be few misunderstandings about the way you use classes.
First, I would recommend reading the Python docs to get the basic idea: http://docs.python.org/2/tutorial/classes.html
To create a class, you simply do
class Animal:
def __init__(self, name, sound): # class constructor
self.name = name
self.sound = sound
And now you can create name objects by calling a1 = Animal("Leo The Lion", "Rawr") or so.
To inherit a class, you do:
# Define superclass (Animal) already in the class definition
class Dog(Animal):
# Subclasses can take additional parameters, such as age
def __init__(self, age):
# Use super class' (Animal's) __init__ method to initialize name and sound
# You don't define them separately in the Dog section
super(Dog, self).__init__("Dog", "Woof")
# Normally define attributes that don't belong to super class
self.age = age
And now you can create a simple Dog object by saying d1 = Dog(18) and you don't need to use d1 = Dog(Animal), you already told the class that it's superclass is Animal at the first line class Dog(Animal):
To create an instance of a class you do
mark = Dog()
not mark = Dog(Animal).
Don't do this implimented stuff. If you want a class that you can't instantiate (i.e. you have to subclass first), do
import abc
class Animal(object):
__metaclass__ = abc.ABCMeta
def speak(self):
...
Since age in the given example is not part of the parent (or base) class, you have to implement the the function (which in a class is called method) in the class which inheritted (also known as derived class).
class Dog(Animal):
# Subclasses can take additional parameters, such as age
def __init__(self, age):
... # Implementation can be found in reaction before this one
def give_age( self ):
print self.age

Categories