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

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

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()

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 to not run init based on __new__ method

I have the following class, which acts as a collection of people:
class Person:
PERSONS = dict() # name ==> instance
def __new__(cls, *args, **kwargs):
name = kwargs.get('name') or '' if not args else args[0]
print ('Name: %s' % name)
if name in cls.PERSONS:
print ('Returning found person!')
return cls.PERSONS[name]
else:
print ('Initializing new person')
return super(Person, cls).__new__(cls)
def __init__(self, name):
print ("Running init")
self.name = name
Person.PERSONS[name] = self
If a person is found, it returns that person, otherwise it creates a new one. And when I run it it works:
>>> p1 = Person('Julia')
Name: Julia
Initializing new person
Running init
>>> p2 = Person('Julia')
Name: Julia
Returning found person!
Running init # <== how to get this not to run?
>>> p1 is p2
True
However, if the person is found, I don't want the __init__ method to run. How would I "skip" the init method based on the return of the __new__ ?
One option is to add a conditional in the __init__, such as:
def __init__(self, name):
if name in Person.PERSONS: return # don't double-initialize
print ("Running init")
self.name = name
Person.PERSONS[name] = self
But I was hoping there might be a cleaner approach.
#MadPhysicist's idea of using a metaclass with a custom __call__ method is correct but the implementation included in the answer is quite off. Instead, the custom __call__ method should use the name of the person, rather than a new Person object, to check if a given name has an existing entry in the PERSONS dict:
class PersonMeta(type):
def __call__(cls, name):
print ('Name: %s' % name)
if name in cls.PERSONS:
print ('Returning found person!')
return cls.PERSONS[name]
print('Initializing new person')
obj = cls.__new__(cls, name)
cls.__init__(obj, name)
cls.PERSONS[name] = obj
return obj
class Person(metaclass=PersonMeta):
PERSONS = dict() # name ==> instance
def __init__(self, name):
print ("Running init")
self.name=name
p1=Person('Julia')
p2=Person('Julia')
print(p1 is p2)
This outputs:
Name: Julia
Initializing new person
Running init
Name: Julia
Returning found person!
True
Instead of trying to skip __init__, put your initialization in __new__. In general, most classes should only implement one of __new__ and __init__, or things get messy.
Also, trying to have a class act as a collection of anything is usually a bad idea. Instead of trying to make your class itself manage its instances, it tends to be a better idea to give that role to a dedicated collection object. This makes it easier to manage object lifetimes, have multiple containers, avoid weird __new__ problems, etc.
The problem I find in your approach is that the __new__ dunder method is triggered just before the __init__. Once said that, it's not that easy to change that behavior.
Instead of handling the new Person's creation inside __new__, create a class method (e.g. create_person) and update the PERSONS dict if needed.
class Person:
def __init__(self, name):
print("Running init\n")
self.name = name
class PersonFactory:
PERSONS = dict()
#classmethod
def create_person(cls, name):
print('Name: %s' % name)
if name in cls.PERSONS:
print ('Returning found person!')
return cls.PERSONS[name]
print('Initializing new person')
cls.PERSONS[name] = Person(name)
return cls.PERSONS[name]
if __name__ == '__main__':
PersonFactory.create_person('Julia')
PersonFactory.create_person('Julia')

class and methods in python. introduction in oop

class Person:
def __init__(self, name):
"""Make a new person with the given name."""
self.myname = name
def introduction(myname):
"""Returns an introduction for this person."""
return "Hi, my name is {}.".format(myname)
# Use the class to introduce Mark and Steve
mark = Person("Mark")
steve = Person("Steve")
print(mark.introduction())
print(steve.introduction())
its suppose to produce
"Hi, my name is Mark." or "Hi, my name is Steve."
but instead it produces
"Hi, my name is undefined."
It should be printing the object's representation in memory (something along the lines of Hi, my name is <__main__.Person object at 0x005CEA10>).
The reason is that the first argument of a method is expected to be the object that the method is called upon.
Just like you have def __init__(self, name): you should have def introduction(self, myname):.
Then you will encounter another problem, as introduction now expects an argument myname which you don't provide. However, it is not needed now since you have access to self.myname.
class Person:
def __init__(self, name):
"""Make a new person with the given name."""
self.myname = name
def introduction(self):
"""Returns an introduction for this person."""
return "Hi, my name is {}.".format(self.myname)
# Use the class to introduce Mark and Steve
mark = Person("Mark")
steve = Person("Steve")
print(mark.introduction())
print(steve.introduction())
Will output
Hi, my name is Mark.
Hi, my name is Steve.
You need to declare introduction() -> introduction(self) as an instance method (by passing in self) to be able to access the instance variable self.myname.
class Person:
def __init__(self, name):
"""Make a new person with the given name."""
self.myname = name
def introduction(self):
"""Returns an introduction for this person."""
return "Hi, my name is {}.".format(self.myname)
Sample output:
# Use the class to introduce Mark and Steve
mark = Person("Mark")
steve = Person("Steve")
print(mark.introduction())
print(steve.introduction())
>>> Hi, my name is Mark.
>>> Hi, my name
Please note however, that the first parameter in a function within a class is reserved for either a class, or object to pass itself to (unless a #staticmethod tag is applied to the method, then the first implicit parameter is not passed; which essentially behave as module methods).
Also keep in mind that self is not a reserved word, so you could name it anything (even though self is PEP convention). The below example executes the same output as the example above, and is semantically the same.
def introduction(myname):
"""Returns an introduction for this person."""
return "Hi, my name is {}.".format(myname.myname)
9.3.5. Class and Instance Variables
Your problem is that your giving your introduction method the parameter myname, but never supplying it with a valid argument.You can simply do:
mark = Person(" Mark")
steve = Person(" Steve")
print(mark.introduction(mark.myname))
print(steve.introduction(steve.myname))
your giving the introduction method, the variable from your class myname.
But the above is not even necessary. Since your initializing your name variable in the __init__ method of your class, it is like a global variable. So you can simply say:
class Person:
def __init__(self, name):
"""Make a new person with the given name."""
self.myname = name
def introduction(self):
"""Returns an introduction for this person."""
return "Hi, my name is{}".format(self.myname)
# Use the class to introduce Mark and Steve
mark = Person(" Mark")
steve = Person(" Steve")
print(mark.introduction())
print(steve.introduction())

__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