Why is self not defined in my program - python

The first part of the program defines the class and the second part calls on the class though a different program as it follows but I keep getting a "TypeError: check_mood() missing 1 required positional argument: 'self' " for line 5 in the second part
import random
class Animal:
#initialize attributes
def __init__(self,animal_type, name, mood):
self.__animal_type = animal_type
self.__name = name
self.__mood = mood
# set methods
def set_animal_type(self, animal_type):
self.__animal_type = animal_type
def set_name(self, name):
self.__name = name
def set_mood(self, mood):
self.__mood = mood
#check mood
def check_mood(self):
integer = random.randint(1,3)
if integer == 1:
self.__mood = "happy"
elif integer == 2:
self.__mood = "hungry"
elif integer == 3:
self.__mood = "sleepy"
#return methods
def get_animal_type(self):
return self.__animal_type
def get_name(self):
return self.__name
def get_mood(self):
return self.__mood
And I made a simple test program to run it through:
import Animal
an = input("enter aninal:")
na = input("enter name:")
mo = Animal.Animal.check_mood()
animals = Animal.Animal(an,na,mo)
print(animals.get_animal_type(), animals.get_name(), animals.get_mood())

You're trying to run a class method without instantiating your class first:
Animal.Animal.check_mood()
This will not work, unless check_mood() is a class method or a static method.
You need to instantiate your class and run your method on an instance
dog = Animal()
dog.check_mood()
or use a static method or a class method.
A static method is a function that does not receive an implicit first argument (like self in an instance method) and is thus just a regular function.
A class method is a function that receives the class itself, rather than an instance, as its first argument. This is usually only useful if you want to create an instance of a class from non-standard arguments. This is not likely be useful in this case, since you don't actually need the class within the method.
An example of how you would use a static method:
class Animal(object):
#staticmethod
def check_mood():
#yourfunction
and a class method:
class Animal(object):
#classmethod
def check_mood(cls):
#yourfunction
However, since you're talking about the mood of an animal, I'm assuming you want to instantiate an animal first, then check its mood.

check_mood() is an instance method - it needs a particular animal whose mood it checks. But here
mo = Animal.Animal.check_mood()
You're asking for the mood of the Animal class itself. Instead, call it from __init__ like this:
self.check_mood()
You would then delete the line giving you the current error, pass only two arguments to Animal(), and modify the def __init__ line so that it no longer expects a mood (since the Animal itself generates it randomly).

Related

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

Calling a method returns <__main__ XYZ object at 0x01234567>

I'm going through a web-based python tutorial and the code below executes in the web environment the class has provided.
However, when I try to run the code locally in Anaconda I get the following result:
I'm Fido. I feel <bound method Pet.mood of <__main__.Pet object at 0x00000223BD4B74E0>>.
I see how using class and superclass can make my code better, and trying to figure out how to get the web based examples to work locally.
Here's the code:
class Pet:
def __init__(self, name = 'Kitty'):
self.name = name
def mood(self):
#code simplified for SO example
return 'happy'
def __str__(self):
state = " I'm {}. I feel {}.".format(self.name, self.mood)
return state
class Cat(Pet):
def chasing_rats(self):
return "I'll get you!"
p1 = Pet("Fido")
print(p1)
self.mood is an instance method of the class Pet. So you need to call it as a method by including the parentheses as self.mood()
class Pet:
def __init__(self, name = 'Kitty'):
self.name = name
def mood(self):
#code simplified for SO example
return 'happy'
def __str__(self):
state = " I'm {}. I feel {}.".format(self.name, self.mood())#updated this line
return state
class Cat(Pet):
def chasing_rats(self):
return "I'll get you!"
p1 = Pet("Fido")
print(p1)
OUTPUT
I'm Fido. I feel happy.

How do I get rid of unneeded parameters in a class initiation?

So I'm trying to get the hang of OOP in Python. The problem I have is when initializing my objects for sub-classes, I'm still having to input information which I shouldn't need to.
Specifically, I'm trying to make it so I can create a Person object without specifying can_speak. So I could do something like:
John = person("John Anderson")
Without having to input can_speak as part of the initialization.
class Animal(object):
def __init__(self, name, can_speak):
self.name = name
self.can_speak = False
class Dog(Animal):
pass
class Person(Animal):
def __init__(self, name, can_speak):
self.name = name
self.can_speak = True
Bob = Person("Bob the Builder", 3.141)
print(Bob.name)
print(Bob.can_speak)
# Bob the Builder
# True
Sam = Dog("Sam the Mutt", 0.00059)
print(Sam.name)
print(Sam.can_speak)
# Sam the Mutt
# False
Here I have to put something as the second input into the initialization, or I get an error. It's a waste like this.
You do not have to add a parameter for every attribute an object has. You can simply fill it in at the Animal level, and override it at the Person level, like:
class Animal(object):
def __init__(self, name): # look ma, no can_speak parameter
self.name = name
self.can_speak = False
class Dog(Animal):
pass
class Person(Animal):
def __init__(self, name): # look ma, no can_speak parameter
super().__init__(name) # perform a super call
self.can_speak = True # override the can_speak
You only have to add a parameter if how such an object should be constructed depends on input.
Furthermore note that you do not have to add such an attribute is attached to an object. You can attach attributes to classes, or define methods. For instance:
class Animal(object):
can_speak = False
def __init__(self, name): # look ma, no can_speak parameter
self.name = name
class Dog(Animal):
pass
class Person(Animal):
can_speak = True
Now we store whether an Animal can speak in the class. This will result in less memory usage, whereas we can still get whether an animal can speak:
>>> a = Animal('foo')
>>> a.can_speak
False
>>> p = Person('bar')
>>> p.can_speak
True
We can however still add an attribute can_speak to an individual dog (in Belgium for instance, there was a television show about a fictitious speaking dog named Samson):
>>> samson = Dog('Samson')
>>> samson.can_speak = True
>>> samson.can_speak
True
>>> foo = Dog('other dog')
>>> foo.can_speak
False
Assuming Animal is the Base class having an attribute can_speak Defaulted to the variable passed into the constructor, which is again defaulted to False.
In the child class Dog is calling its base constructor so it can't speak. But Person is calling the base constructor with a True value for can_speak.
So you can create an object of person which can't speak as well as an animal which can speak(such as parrot). By following the below method the can_speak variable remains constant throughout all the classes and not duplicated in child classes and can be changed by passing an argument instead of changing manually within child class.
Try the following
class Animal(object):
def __init__(self, name, can_speak=False):
self.name = name
self.can_speak = can_speak
class Dog(Animal):
pass
class Person(Animal):
def __init__(self, name, can_speak=True):
super(Person, self).__init__(name, can_speak)
Bob = Person("Bob the Builder")
print(Bob.name)
print(Bob.can_speak)
# Bob the Builder
# True
Sam = Dog("Sam the Mutt")
print(Sam.name)
print(Sam.can_speak)
# Sam the Mutt
# False
First you should always use the built-in function super() and call parent's __init__() unless you are really sure you don't want to do that. The parent can initialize more than those two attributes and you would have to copy it into children's __init__() which is highly error-prone.
Now you can accomplish your task in several ways:
Use default value
class Person(Animal):
def __init__(self, name, can_speak = True):
super().__init__(name, can_speak)
In that case you still can create instance of Person and set that he can't speak (he can be speechless).
If you don't want to support speechless people then you can do this:
class Person(Animal):
def __init__(self, name, can_speak = True):
super().__init__(name, True)
But then the parameter can be misleading so you can omit that (from this point the parent and child has different constructor parameters which is usually not a problem):
class Person(Animal):
def __init__(self, name):
super().__init__(name, True)

call a static method or property in __init__ in python

I have many Questions !
look at this code plz:
class Dog(object):
_the_most_oldest = int()
def __init__(self,age):
self.age=age
#staticmethod
#property
def the_most_oldest(age):
if Dog._the_most_oldest < age:
Dog._the_most_oldest=age
return Dog._the_most_oldest
1 :
is it maybe that a property be a static method ??
beacuse I need a really static var that share between instances -> _the_most_oldest dog ! => so I need #property . and because the_most_oldest(age) method is not for any special instance I need #staticmethod !
2 :
the second thing I need to do is in every instace the_most_oldest shuold be call and calculate and refresh _the_most_oldest var. how do that ?
this have Error :
def __init__(self,age):
self.age=age
the_most_oldest(self.age)
No, property can not be static method (it's not a method it's descriptor).
Create class attribute which will hold all instances of that class.
class Dog(object):
_dogs = []
And put new instances in the _dogs class attribute.
def __init__(self, age):
self._dogs.append(self)
self.age = age
And then create classmethod the_most_oldest. Which will calculate the most oldest dog of all instances.
#classmethod
def the_most_oldest(cls):
return max(cls._dogs, key=lambda dog: dog.age)
In your place I would initialize _the_most_oldest = 0 (and maybe call it _the_oldest, better english)
A #staticmethod in Python is just a function "contained in a class" in your case I think it would be better to use #classmethod.
If you want to assign a value to a property you can not use the decorator, you need to pass a setter and a getter method.
def _get_oldest(self):
return self._the_oldest
def _set_oldest(self, age):
if Dog._the_oldest < age:
Dog._the_oldest=age
the_oldest = property(_get_oldest, _set_oldest)

__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