Creating objects in Python way - python

I'm learning Python and recently started with the OOP part.
I know there are different ways to create objects but I do not know what way I should aim at.
Create objects with arguments or without arguments?
Then I do understand the best way to change the attributes is with method calls.
Code:
class Human(object):
def __init__(self):
self.name = ''
self.age = 0
def set_name(self, name):
self.name = name
def set_age(self, age):
self.age = age
class Humans(object):
def __init__(self, name, age):
self.name = name
self.age = age
def set_names(self, name):
self.name = name
def set_ages(self, age):
self.age = age
# Create object without arguments
boy = Human()
boy.set_name('Peter')
boy.set_age(30)
# Or create object with arguments
girl = Humans('Sandra', 40)

An object should be in an usable state after creation. That said, a human with no name and no age is not useful. So the second implemention is preferred. Another thing is, that you don't need setters in python, which reduces the class to
class Humans(object):
def __init__(self, name, age):
self.name = name
self.age = age

Related

TypeError: 'str' object is not callable oop

Im new to oop with python. Why am I getting this error? Shouldnt it print tom and 12?
class Dog:
def __init__(self,name,age):
self.name = name
self.age = age
def name(self):
return self.name
def age(self):
return self.age
dog = Dog("tom", 12)
print(dog.name())
print(dog.age())
Instance attributes take precedence over class attributes when one of each exists and they have the same name. If you are going to have a method that returns the value of an attribute, a common convention is to make the name of the instance attribute a "private" version of the method name by prefixing an underscore to the name.
class Dog:
def __init__(self, name, age):
self._name = name
self._age = age
def name(self):
return self._name
def age(self):
return self._age
However, until you have a good reason to hide the attribute behind a getter, just expose the attribute as part of the public interface.
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
d = Dog("tom", 12)
print(dog.name)
If you later decide to hide the attribute behind a getter and/or setter, you can use a property to do so without changing the public interface.
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
#property
def name(self):
return self._name
#name.setter
def name(self, v):
self._name = v
d = Dog("tom", 12)
print(dog.name) # Works the same as before
name is a variable and name is also a function.
Therefore this error.
Just do print(self.name)
you have to create class and change the name of funtion like this
class Dog:
def __init__(self,name,age):
self.name = name
self.age = age
def Name(self):
return self.name
def age(self):
return self.age
dog = Dog("tom", 12)
print(dog.name())
print(dog.age())

Is following declaration of class atributes as None correct?

When & why would someone write class as follows:
1.
class Cat:
name = None
age = None
def __init__(self, name, age):
self.name = name
self.age = age
instead of simple:
2.
class Cat:
def __init__(self, name, age):
self.name = name
self.age = age
or with general class attribute:
3.
class Cat:
species = 'mammal'
def __init__(self, name, age):
self.name = name
self.age = age
Would you ever use the #1. example?
Would you consider it correct?

TypeError: __init__() takes 3 positional arguments but 4 were given

These are the codes for my classes:
class Employee:
def __init__(self, name, gender):
self.name = name
self.gender = gender
class Salary:
def jump(self, name, salary):
print(self.name, self.salary)
class Male(Salary, Employee):
def __init__(self, name, gender, occupation):
super(Male, self).__init__(name, gender, occupation)
self.occupation = occupation
# Separate from all classes (list of instantiated objects)
employee1 = Male("Jim", "male", "technician")
print(Male.name)
When I use the last two lines of the code after creating all my classes, a 'TypeError: init() takes 3 positional arguments but 4 were given' error occurs referencing the super(Male, self).... and employee1 = Male(... lines.
Under Pet you have:
def __init__(self, name, color):
self.name = name
self.color = color
Under Dog you have:
def __init__(self, name, color, owner):
super(Dog, self).__init__(name, color, owner)
Under Dog there's an extra owner positional argument given, which leads to this error. On a side note, I think super().__init__(name, color) works just as well too in Python 3
class Employee:
def __init__(self,name,gender):
self.name=name
self.gender=gender
class Salary:
def __init__(self,name,gender):
self.name=name
self.gender=gender
def jump(self):
print(self.name,self.salary)
class Male(Salary,Employee):
def __init__(self,name,gender,occupation):
self.occupation=occupation
super().__init__(name,gender)
employee1 = Male("Jim","male","technician")
print(employee1.name)
""" You were writing the occupation parameter in the super, but super calls to the parent class and your parent class does not have occupation parameter. The occupation belongs only to the Class Male."""
class Employee:
def __init__(self, name, gender):
self.name = name
self.gender = gender
class Salary:
def __init__(self, name, gender):
self.name = name
self.gender = gender
def jump(self):
print(self.name, self.salary)
class Male(Salary, Employee):
def __init__(self, name, gender, occupation):
self.occupation = occupation
Employee.__init__(self, name, gender)
Salary.__init__(self, name, gender)
employee1 = Male("Jim", "male", "technician")
print(employee1.name)
Python - Inheritance
To access all the methods and properties of base class Employee, super() function is used in derived class Male.
Syntax for using super function is shown in example.
Along with this, use print(employee1.name) instead of print(Male.name).

Initializing Python class object with external data

Suppose a "person" class contains name, age and phone number.
When creating a person object, I would like to set phone number by looking up an external phone book rather than explicitly passing a phone number.
Option 1: Store phone book as a class variable
class person():
phonebook = {}
def __init__(self, name, age):
self.name = name
self.age = age
self.phone = self.phonebook[self.name]
person.phonebook = {'dan':1234}
dan = person('dan', 30)
Option 2: Create a class object without phone number then have a separate function to load it.
class person():
def __init__(self, name, age):
self.name = name
self.age = age
def loadphone(self, phone):
self.phone = phone
phonebook = {'dan':1234}
dan = person('dan',30)
dan.loadphone(phonebook['dan'])
Both solutions do not seem optimal. Option 1, every person carries a phone book (unnecessarily). Option 2 requires 2-step initialization.
Is there a better way to create a person object without 1) explicitly passing a phone number or phone book during initialization, 2) storing phone book as a class variable, and 3) requiring a multi-step initialization?
As discussed in this post, defining a variable outside of any methods in the class, while still being defined in a class makes it a static variable, such as the one you have:
class person():
phonebook = {}
This means that there is a single phonebook which all instances of the class refer to
person.phonebook{'dave':1234, 'joey':5678}
dave = person('dave', 30)
joey = person('joey', 23)
There is still only the one universal phonebook that all instances refer to. The one thing to change in that code is that you should not define it as self.phonebook['dave'] so it should look like
class person():
phonebook = {}
def __init__(name, age):
self.name = name
self.age = age
self.number = phonebook[name]
Are you wanting to optionally define a phone number for a Person? You could do something like below:
class Person():
def __init__(self, name, age, phone=None):
self.name = name
self.age = age
self.phone = phone
dan = Person('dan',30, phone=1234)
stan = Person('stan', 60)
Firstly, as for me, it's too wide question and very depend on task. In one case you can access to PhoneBook, in another - it's bad idea (e.g. PhoneBook load data from server and creating 1000 of Person will produce 1000 requests).
Secondary, their is next approach:
class BasicPerson():
def __init__(self, name, age):
self.name = name
self.age = age
def ToString(self):
return('some code')
class PersonWithPhone():
def __init__(self, basicPerson, phone):
self.basicPerson = basicPerson
self.phone = phone
def ToString(self):
return('another code ' + self.basicPerson.ToString())
person = PersonWithPhone(BasicPerson('', ''), '11111')
It's just example and may seems useless, but in many situations you can extract some core actions (ToString, for example) and than wrote small decorators that expand each other.

TypeError: __init__() takes exactly 4 arguments (1 given)

I need help , I have the following classes in Python with inheritance and I have an error:
class Human:
def __init__(self,name,surname,age):
self.name = name
self.surname = surname
self.age = age
def getName(self):
return self.name
def getSurname(self):
return self.surname
def setName(self, name):
self.name = name
def setSurname(self, surname):
self.surname = surname
def setAge(self, age):
self.age = age
def getAge(self):
return self.age
pass
and:
from Human import Human
class Student(Human):
def __init__(self,name,surname,age,file):
Human().__init__(self,name, surname, file)
self.file = file
def getFile(self):
return self.file
def setFile(self, file):
self.file = file
pass
When I instantiate me the following error
from Student import Student
student1 = Student("Jhon", "Santana", "20", "111000")
Error:
Human().__init__(self, name, surname, age)
TypeError: __init__() takes exactly 4 arguments (1 given)
which is the cause of this error? Thanks...
Human().__init__(self,name, surname, age)
thats not how you create an instance of your class
you should do:
Human.__init__(self,name, surname, age)
without the () .otherwise you try to create an instance of it in Human()
dont instanciate your parent class
def __init__(self,name,surname,age,file):
Human.__init__(self,name, surname, file)
or even better
super(Human,self).__init__(name,surname,age)
Try this:
class Human:
def __init__(self,name,surname,age):
self.name = name
self.surname = surname
self.age = age
def getName(self):
return self.name
def getSurname(self):
return self.surname
def setName(self, name):
self.name = name
def setSurname(self, surname):
self.surname = surname
def setAge(self, age):
self.age = age
def getAge(self):
return self.age
class Student(Human):
def __init__(self, name,surname,age,file):
super().__init__(name, surname, age)
self.file = file
def getFile(self):
return self.file
def setFile(self, file):
self.file = file
student1 = Student("Jhon", "Santana", "20", "111000")
input()
When you inherit another class but want to overwrite some of the attributes, you need to add the parent class's attributes that you want to overwrite in the super constructor so that the attributes passed into the student class can be passed straight into the parent class.
Feel free to watch my video on inheritance at the following address:
https://www.youtube.com/watch?v=cqRtcmPGcic
As detailed here, the use of super is prefered:
def __init__(self, name, surname, age, file):
super(Human, self).__init__(name, surname, age)
self.file = file

Categories