Trying to create a object from a class by calling a function - python

I am working on a project that I need to create some objects dynamically from a class. I am not asking for anyone to solve it but just point me in the right direction. An example would be if I was working with Dogs.
class Dog(object):
"""Creating Dogs"""
def __init__(self, name, age, gender):
super(Dog, self).__init__()
self.name = name
self.name = age
self.name = gender
I would like however to have a function that I can pass this information into that would create a global object. The function would look like this:
def create_dog(name, age, gender):
name = Dog(name,age, gender)
return(name)
So theoretically if I passed the name "Jack" to the function I would have a object globally called "Jack" from the class. I am just trying to find a good way to do this if any. If this is completely against python I will figure out another way but I am sitting here stuck. I have also thought about nesting the class within my function but the namespace won't go into global.

you could create a global dictionary
dogs = {}
def create_dog(name, age, gender):
# maybe check if already exists
dogs[name] = Dog(name, age, gender)

With changing locals: (which is still bad, but not as much as changing globals)
def create_dog(name, age, gender, locals_=locals()):
dog = Dog(name, age, gender)
locals_[name] = dog
create_dog("jack", 3, "male")
print(jack)

Maybe you want to make an alternative constructor ?
class Dog(object):
"""Creating Dogs"""
def __init__(self, name, age, gender):
super(Dog, self).__init__()
self.name = name
self.name = age
self.name = gender
#classmethod
def create_dog(name, age, gender):
name = Dog(name,age, gender)
return name
See also discussion Meaning of #classmethod and #staticmethod for beginner?
A global dictionary is fine if you use a single file script, but for a more complex software you'll have to import all the 3 elements:
from dogs import dogs, create_dog, Dog
With class attribute you import just one name space. So you could do this:
class Dog(object):
"""Creating Dogs"""
members = []
def __init__(self, name, age, gender):
super(Dog, self).__init__()
self.name = name
self.name = age
self.name = gender
#classmethod
def create_dog(name, age, gender):
name = Dog(name,age, gender)
Dog.members.append(name)
return name
Now you can simply import Dog, and access the class attribute Dog.members

Related

How to create instance of multiple inherited class?

I have this code:
class Person:
def __init__(self, name, last_name, age):
self.name = name
self.last_name = last_name
self.age = age
class Student(Person):
def __init__(self, name, last_name, age, indexNr, notes):
super().__init__(name, last_name, age)
self.indexNr = indexNr
self.notes = notes
class Employee(Person):
def __init__(self, name, last_name, age, salary, position):
super().__init__(name, last_name, age)
self.salary = salary
self.position = position
class WorkingStudent(Student, Employee):
def __init__(self, name, last_name, age, indexNr, notes, salary, position):
Student.__init__(name, last_name, age, indexNr, notes)
Employee.__init__(name, last_name, age, salary, position)
I want to create a WorkingStudent instance like this:
ws = WorkingStudent("john", "brown", 18, 1, [1,2,3], 1000, 'Programmer')
but it's not working, I get this error:
TypeError: __init__() missing 1 required positional argument: 'notes'
Or what I am doing wrong here? Also, I have already tried super() in WorkingStudent class but it calls only the constructor of the first passed class. i.e in this case Student
Note: I have already gone through multiple StackOverflow queries but I couldn't find anything that could answer this. (or maybe I have missed).
Instead of explicit classes, use super() to pass arguments along the mro:
class Person:
def __init__(self, name, last_name, age):
self.name = name
self.last_name = last_name
self.age = age
class Student(Person):
def __init__(self, name, last_name, age, indexNr, notes, salary, position):
# since Employee comes after Student in the mro, pass its arguments using super
super().__init__(name, last_name, age, salary, position)
self.indexNr = indexNr
self.notes = notes
class Employee(Person):
def __init__(self, name, last_name, age, salary, position):
super().__init__(name, last_name, age)
self.salary = salary
self.position = position
class WorkingStudent(Student, Employee):
def __init__(self, name, last_name, age, indexNr, notes, salary, position):
# pass all arguments along the mro
super().__init__(name, last_name, age, indexNr, notes, salary, position)
# uses positional arguments
ws = WorkingStudent("john", "brown", 18, 1, [1,2,3], 1000, 'Programmer')
# then you can print stuff like
print(f"My name is {ws.name} {ws.last_name}. I'm a {ws.position} and I'm {ws.age} years old.")
# My name is john brown. I'm a Programmer and I'm 18 years old.
Check mro:
WorkingStudent.__mro__
(__main__.WorkingStudent,
__main__.Student,
__main__.Employee,
__main__.Person,
object)
When you create an instance of WorkingStudent, it's better if you pass keyword arguments so that you don't have to worry about messing up the order of arguments.
Since WorkingStudent defers the definition of attributes to parent classes, immediately pass all arguments up the hierarchy using super().__init__(**kwargs) since a child class doesn't need to know about the parameters it doesn't handle. The first parent class is Student, so self.IndexNr etc are defined there. The next parent class in the mro is Employee, so from Student, pass the remaining keyword arguments to it, using super().__init__(**kwargs) yet again. From Employee, define the attributes defined there and pass the rest along the mro (to Person) via super().__init__(**kwargs) yet again.
class Person:
def __init__(self, name, last_name, age):
self.name = name
self.last_name = last_name
self.age = age
class Student(Person):
def __init__(self, indexNr, notes, **kwargs):
# since Employee comes after Student in the mro, pass its arguments using super
super().__init__(**kwargs)
self.indexNr = indexNr
self.notes = notes
class Employee(Person):
def __init__(self, salary, position, **kwargs):
super().__init__(**kwargs)
self.salary = salary
self.position = position
class WorkingStudent(Student, Employee):
def __init__(self, **kwargs):
# pass all arguments along the mro
super().__init__(**kwargs)
# keyword arguments (not positional arguments like the case above)
ws = WorkingStudent(name="john", last_name="brown", age=18, indexNr=1, notes=[1,2,3], salary=1000, position='Programmer')
Problem: we have a lot of arguments for our most derived class, that need to be used to initialize all the bases. However, in Python's multiple inheritance system with super(), the class that will be initialized next depends on an MRO (method resolution order) that may have been determined in another class. Therefore, when we use multiple inheritance, we don't know which class will have its __init__ called when we use super().
Solution: use consistent names for the parameters, and then take advantage of **kwargs, so that each class takes in the (explicitly named) parameters it cares about, and forwards the rest.
That looks like:
class Person:
def __init__(self, name, last_name, age):
self.name = name
self.last_name = last_name
self.age = age
class Student(Person):
def __init__(self, indexNr, notes, **kwargs):
super().__init__(**kwargs)
self.indexNr = indexNr
self.notes = notes
class Employee(Person):
def __init__(self, salary, position, **kwargs):
super().__init__(**kwargs)
self.salary = salary
self.position = position
class WorkingStudent(Student, Employee):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Forcing the client code to use keyword arguments is more work for the clients, but it also helps guard against errors from mistaking the order of positional arguments.
This is the easiest way to reach your goal.
If your WorkingStudent class inherite Student and Employee class like this ,
class WorkingStudent(Student, Employee):
def __init__(self, name, last_name, age, indexNr, notes, salary, position):
Student.__init__(self, name, last_name, age, indexNr, notes)
Employee.__init__(self, name, last_name, age, salary, position)
ws = WorkingStudent("john", "brown", 18, 1, [1, 2, 3], 1000, 'Programmer')
print(ws)
print(ws.name)
print(ws.age)
your output will be...
Output:
<main.WorkingStudent object at 0x7fc6c4d8ba10>
john
18
[1, 2, 3]

Is there another way to get value from object method into object variable

I made code that goes like this
class Dog():
def breed():
return "rottwiller"
def __init__(self, name, age, breed=breed()):
self.name = name
self.age = age
self.breed = breed
Is there another way to achieve "self.breed" value instead of breed=breed(), but through function method as well.
for example something similar to this( I have tried out this that does not work):
def __init__(self, name, age):
self.name = name
self.age = age
self.breed = breed()
You shouldn't name an attribute and a method the same thing. That being said, my suspicions for why you are asking this question tell me I should point you towards the #property decorator.
class Dog():
def __init__(self, name, age, breed):
self.name = name
self.age = age
self._breed = breed
#property
def breed(self):
return self._breed
This is overkill for your example, but if you have a Dog class and a specific breed, I imagine you are thinking about subclasses and possibly more complicated things than you are doing here. Essentially, the #property decorator will allow you to access breed as an attribute, and will return the value of the call to the function you define under it by the same name.
There are a number of issues with the code posted.
The breed method is overwritten in __init__ method as you set the breed attribute. So the method should be renamed.
The breed method needs to specify the first argument self.
class Dog:
def get_breed(self):
return "rottwiller"
def __init__(self, name, age):
self.name = name
self.age = age
self.breed = self.get_breed()

Python accessor and mutator methods

I am trying to solve a Python question that was described as follows:
Design a class that holds the following personal data: name, address,
age, and phone number. Write appropriate accessor and mutator methods.
Also, write a program that creates three instances of the class. One
instance should hold your information, and the other two should hold
your friends’ or family members’ information.
I am stumped on where to go from here. I think I have 90% correct but I am missing the main function code. My code is as follows:
class Person:
def __init__(self, name, address, age, phone):
self.__name = name
self.__address = address
self.__age = age
self.__phone_number = phone
#Set methods
def set_name(self,name):
self.__name = name
def set_address(self,address):
self.__address = address
def set_age(self,age):
self.__age = age
def set_phone(self,phone):
self.__phone = phone
#Get methods
def get_name(self):
reurn self.__name
def get_address(self):
reurn self.__address
def get_age(self):
reurn self.__age
def get_phone(self):
reurn self.__phone
def main():
#not sure what to put here?????
main()
You've created the blueprint for your objects. That's your Person class. Now it's time to build some Person's. You can do that with
p1 = Person("Your Name", "Address", 12, "phone_number")
p2 = etc
p3 = etc
You can access your getter and setter methods from your objects e.g.
p1.set_name("Joe")
print(p1.get_name()) # outputs "Joe"

Python class input argument

I am new to OOP. My idea was to implement the following class:
class name(object, name):
def __init__(self, name):
print name
Then the idea was to create two instances of that class:
person1 = name("jean")
person2 = name("dean")
I know, that is not possible, but how can I pass an input-argument into an instance of a class?
The problem in your initial definition of the class is that you've written:
class name(object, name):
This means that the class inherits the base class called "object", and the base class called "name". However, there is no base class called "name", so it fails. Instead, all you need to do is have the variable in the special init method, which will mean that the class takes it as a variable.
class name(object):
def __init__(self, name):
print name
If you wanted to use the variable in other methods that you define within the class, you can assign name to self.name, and use that in any other method in the class without needing to pass it to the method.
For example:
class name(object):
def __init__(self, name):
self.name = name
def PrintName(self):
print self.name
a = name('bob')
a.PrintName()
bob
>>> class name(object):
... def __init__(self, name):
... self.name = name
...
>>> person1 = name("jean")
>>> person2 = name("dean")
>>> person1.name
'jean'
>>> person2.name
'dean'
>>>
You just need to do it in correct syntax. Let me give you a minimal example I just did with Python interactive shell:
>>> class MyNameClass():
... def __init__(self, myname):
... print myname
...
>>> p1 = MyNameClass('John')
John
Remove the name param from the class declaration. The init method is used to pass arguments to a class at creation.
class Person(object):
def __init__(self, name):
self.name = name
me = Person("TheLazyScripter")
print me.name
Actually you can!
How about this?
class name(str):
def __init__(self, name):
print (name)
# ------
person1 = name("jean")
person2 = name("dean")
print('===')
print(person1)
print(person2)
Output:
jean
dean
===
jean
dean
Python Classes
class name:
def __init__(self, name):
self.name = name
print("name: "+name)
Somewhere else:
john = name("john")
Output:
name: john
class Person:
def init(self,name,age,weight,sex,mob_no,place):
self.name = str(name)
self.age = int(age)
self.weight = int(weight)
self.sex = str(sex)
self.mob_no = int(mob_no)
self.place = str(place)
Creating an instance to class Person
p1 = Person(Muthuswamy,50,70,Male,94*****23,India)
print(p1.name)
print(p1.place)
Output
Muthuswamy
India

Mutually Reference-able Instances in Python

Say I have a pair of instances that reference one another mutually. Is there a preferable manner to structure this relationship than the following.
class Human():
def __init__(self, name):
self.name = name
self.pet = Dog('Sparky', self)
def pet(self, animal):
self.pet.receive_petting()
class Dog(Pet):
def __init__(self, name, owner):
self.name = name
self.owner = owner
def receive_petting(self):
pass
def bark_at(self, person):
"do something"
The thing I don't like is that the relationship needs to be specified in two places. Any ideas on how to make this dryer?
I would break this into three classes:
class Human():
def __init__(self, name):
self.name = name
class Dog(Pet):
def __init__(self, name):
self.name = name
def bark_at(self, person):
"do something"
class OwnerPetRelation():
def __init__(self, dog, human):
self.owner=human
self.pet=dog
Now, one owner can also have many dogs, we just need to define as many OwnerPetRelations.
Similarly, a dog can also belong to multiple owners now.
I would create a method on Human that allows you to add pets (since a human might have many pets):
class Human():
def __init__(self, name):
self.name = name
self.pets = []
def add_pet(self, pet):
pet.owner = self
self.pets.append(pet)
def pet(self, animal):
for pet in self.pets:
pet.receive_petting()
class Dog(Pet):
def __init__(self, name):
self.name = name
self.owner = None
def receive_petting(self):
pass
def bark_at(self, person):
"do something"
This can be used as follows
human = Human('Jim')
human.add_pet(Dog('Woof'))
This approach can of course also be used for just a single pet and one could also extend it to allow pets to be owned by many humans.
There's nothing really Python-specific here; this is just a limitation of constructor-based dependency injection. It's hard to inject a reference to another object that cannot have been created yet. Instead, you can create an object that has a reference to something that will have a reference to the other object. For instance, you can pass a function to the constructor that will be able to return the value:
class Human():
def __init__(self,name,dog):
self.name = name
self._dog = dog
#property
def dog(self):
return self._dog()
class Dog():
def __init__(self,name,human):
self.name = name
self._human = human
#property
def human(self):
return self._human()
Then you can use it like this:
human = None
dog = Dog('fido',lambda: human)
human = Human('john',lambda: dog)
print(dog.human.name)
print(human.dog.name)
john
fido
It is not hard to update this so that the property function caches the value, of course. E.g.:
class Dog():
def __init__(self,name,human):
self.name = name
self._human = human
#property
def human(self):
try:
return self._human_
except AttributeError:
self._human_ = self._human()
return self._human_

Categories

Resources