class Family:
def __init__(self, number_of_family_members):
self.members = self.create_members(number_of_family_members)
def create_members(self, number):
family_people = []
for i in range(number):
family_people.append(Human())
#family_people.append(self.Human())
return family_people
class Human:
def __init__(self):
self.exists = True
I plan on having Family Objects that will contain Human Objects. I am not sure if I am (1) correctly calling the method "create_members" (2) not sure how to initiate Humans
*I am currently learning about Objects so I wasn't sure if this was correct. Thanks!
What's the issue? Your code is fine. You can inspect it on the terminal to see what is happening. You can also simplify the initialization code.
class Family:
def __init__(self, number_of_family_members):
self.members = [Human()] * number_of_family_members
class Human:
def __init__(self):
self.exists = True
>>> f = Family(5)
>>> f.members
[<__main__.Human instance at 0x1102ca560>, <__main__.Human instance at 0x1102ca560>, <__main__.Human instance at 0x1102ca560>, <__main__.Human instance at 0x1102ca560>, <__main__.Human instance at 0x1102ca560>]
Related
I'd like to do some sort of "reversed inheritance", in which I have a class that is initialized as another class, according to input, and has several shared methods as well. I'm not interested in instantiating a different classes for each input, I'd like that to happen 'under the hood'.
I'm looking for the correct way to do the following:
class Carpenter():
def __init__(self):
self.tools = ['saw', 'screwdriver']
self.material = 'wood'
class Baker():
def __init__(self):
self.tools = ['oven', 'mixer']
self.material = 'flour'
class Professional():
def __init__(self, profession, name):
self.name = name
if profession == 'carpenter':
Carpenter.__init__(self)
elif profession == 'baker':
Baker.__init__(self)
def work(self):
print('working')
def go_home(self):
print('finally')
I could do it by performing 'by-the-book' inheritance and calling a function to handle the input-dependent logic:
class Professional():
...
class Carpenter(Professional):
...
class Baker(Professional):
...
def get_professional(profession):
if profession == 'baker':
professional = Baker()
elif profession == 'carpenter':
professional = Carpenter()
return professional
However I've been wondering if there's a more elegant way to do so.
Thanks!
You might want to use a dictionary:
professional = {'baker': Baker, 'carpenter': Carpenter}
then use;
def get_professional(profession):
constructor = professional['profession']
return constructor()
Another way would use the exec function but it would not be a good idea
Disclaimer: I am new to programming and have just started learning about Classes and Inheritance so perhaps it is my lack of understanding which is causing me issues?
I have created two classes in seperate files person.py and address.py.
The person class inherits from the address class however a person can have multiple addresses (postal, physical etc..) How can I inherit multiple instances of my address class to for each type.
My goal is to eventually have a library of common classes for future projects so any help or constructive comments around this concept are much appreciated.
I want to be able to create something like the below code where both the postal and the physical address utilise the Address class:
employee = Person()
employee.set_postal_address("342 Gravelpit Terrace","Bedrock")
employee.set_physical_address("742 Evergreen Tce", "Springfield")
Below is my code, I have not created any reference to Address() in the Person() class as I am not sure how to achieve this?
# address.py
class Address:
def __init__(self):
self.__line1 = None
self.__line2 = None
self.__town_city = None
self.__post_code = None
self.__state_region = None
self.__country = None
# Line 1
def get_line1(self):
return self.__line1
def set_line1(self, line1):
self.__line1 = line1
#etc....
# person.py
from address import *
class Person(Address):
def __init__(self):
self.__first_name = None
self.__last_name = None
self.__postal_address = []
self.__physical_adress = []
def set_postal_address(self):
# use the address class
# return a list of address values
self.__postal_address = []
def set_physical_address(self):
# use the address class
# return a list of address values
self.__physical_address = []
#etc...
Any help is greatly appreciated. If there is a better way of handling this please let me know.
You do not need to necessarily inherit Address when creating the class Person. One way to achieve your goal is to initialize an Address class object within the Person class.
# address.py
class Address:
def __init__(self, **kwargs):
self.__line1 = kwargs.get('__line1')
self.__line2 = kwargs.get('__line2')
self.__town_city = kwargs.get('__town_city')
self.__post_code = kwargs.get('__post_code')
self.__state_region = kwargs.get('__state_region')
self.__country = kwargs.get('__country')
# Line 1
def get_line1(self):
return self.__line1
def set_line1(self, line1):
self.__line1 = line1
#etc....
# person.py
from address import *
class Person:
def __init__(self, **kwargs):
self.__first_name = kwargs.get('__first_name')
self.__last_name = kwargs.get('__last_name')
self.__postal_address = None
self.__physical_address = None
def set_postal_address(self, **kwargs):
# use the address class
self.__postal_address = Address(**kwargs)
def set_physical_address(self, **kwargs):
# use the address class
self.__physical_address = Address(**kwargs)
#etc...
This allows you to keep inherited methods from getting cluttered in a given class object but still allows you to keep nice class structures.
Then you can do something like:
bob=Person(__first_name='Bob', __last_name='Smith')
bob.set_postal_address(__line1='42 Wallaby Way', __town_city='Sydney')
# Since we are using kwargs.get() any not specified Kwarg comes out as None.
# Now `__postal_address` is its own Address class and comes with Address methods
bob.__postal_address.set__line2('Apt 3B')
Now there are times when you would want to inherit common methods from higher level classes. You can read more on python classes here: (https://docs.python.org/3.6/tutorial/classes.html)
import copy
class Myclass0:
paperlist=[]
class Myclass1:
def copy_something(self):
Paper = Myclass0()
Flowers = ["Roses","Sunflower","Tulips","Marigold"]
Paper.paperlist = copy.copy(Flowers)
class Myclass3:
superlist = []
Paper = Myclass0()
print(Paper.paperlist)
superlist.append(paperlist[0])
I am getting a index out of range error on compiling.please help me finding a way to print paperlist of Myclass0 in Myclass3 using class Myclass1 Functions and attributes.You can change the class body but All the Classes should be used.
I am waiting for your valuable efforts.
Thank You
maybe this code snippet could help you understand it better:
class MyClass0:
def __init__(self):
# this is now an attribute of the instance (not the class)
self.paperlist = []
class MyClass1:
#staticmethod
def copy_something(paper):
# this is a static method (it doesnt rely on the Class (MyClass1) or an instance of it
flowers = ["Roses", "Sunflower", "Tulips", "Marigold"]
paper.paperlist = flowers
class Myclass3:
def __init__(self, paper):
# when an instance of this class is created an instance of MyClass0
# must pre passed to its constructor. It then prints out its paperlist
print(paper.paperlist)
paper = MyClass0()
MyClass1.copy_something(paper)
Myclass3(paper)
I'm working on a game using python.
The AI in the game uses variables that the player has, and vice versa.
For an example:
class Player():
def __init__(self, canvas...):
self.id = canvas.create_rectangle(...)
...
def touching_AI(self):
aipos = canvas.coords(AI object)
pos = canvas.coords(self.id)
...
#the function above checks if the player is touching the AI if it
#is, then call other functions
this = player(canvas...)
class AI():
def __init__(self, canvas...):
self.id = canvas.create_rectangle(...)
def chase_player(self):
playerpos = canvas.coords(this.id)
pos = canvas.coords(self.id)
...
# a lot of code that isn't important
Obviously, Python says that the AI object in the player class isn't defined. Both classes depend on the other to work. However, one isn't defined yet, so if I put one before the other, it returns an error. While there is probably a workaround for these two functions only, there are more functions that I didn't mention.
In summary, is there a way (pythonic or non-pythonic) to use and/or define an object before it is created (i.e even making more files)?
you do not
instead use arguments
class Player():
def __init__(self, canvas...):
self.id = canvas.create_rectangle(...)
...
def touching(self,other):
aipos = canvas.coords(other.object)
pos = canvas.coords(self.id)
...
#the function above checks if the player is touching the AI if it
#is, then call other functions
class AI():
def __init__(self, canvas...):
self.id = canvas.create_rectangle(...)
def chase(self,player):
playerpos = canvas.coords(player.id)
pos = canvas.coords(self.id)
then
player = Player(canvas...)
ai = AI(...)
ai.chase(player)
player.touching(ai)
but even better is to define a base object type that defines your interface
class BaseGameOb:
position = [0,0]
def distance(self,other):
return distance(self.position,other.position)
class BaseGameMob(BaseGameOb):
def chase(self,something):
self.target = something
def touching(self,other):
return True or False
then all your things inherit from this
class Player(BaseGameMob):
... things specific to Player
class AI(BaseGameMob):
... things specific to AI
class Rat(AI):
... things specific to a Rat type AI
You do not have a dependency cycle problem. But, you have the following problem,
You are trying it use an AI object, but you did not create the object anywhere. It needs to look like,
foo = AI() #creating the object
bar(foo) #using the object
The syntax is wrong around canvas.coords(AI object).
The way to call a function is foo(obj) without the type.
When defining a function you can optionally mention the type like def foo(bar : 'AI'):
The proof you can depend classes on each other, https://pyfiddle.io/fiddle/b75f2de0-2956-472d-abcf-75a627e77204/
You can initialize one without specifying the type and assign it in afterwards. Python kind of pretends everyone are grown-ups so..
e.g.:
class A:
def __init__(self, val):
self.val = val
self.b = None
class B:
def __init__(self, a_val):
self.a = A(a_val)
a_val = 1
b = B(1)
a = b.a
a.b = b
I have a question which is more regarding OOP in general rather than python specific.
Is ist possible to store instances of ClassA in instance of ClassB without a specific method, i.e. by some kind of inheritance.
Example: let's say I have one Model class and one Variable class
class Model():
def __init__(self):
self.vars = []
def _update_vars(self,Variable):
self.vars.append(Variable)
class Variable(Model):
def __init__(self,**kwargs):
self.__dict__.update(kwargs)
Is it now possible to call _update_vars whenever an instance of variable is being created.
So if I do something like this:
mdl = Model()
varA = Variable(...)
varB = Variable(...)
that mdl.vars would now include varA and varB.
I know that I could easily do this by passing the variables as an argument to a "public" method of Model. So I am not looking for
mdl.update_vars(varA)
So my two questions are:
is this possible?
if yes: would this very non-standard OOP programming?
Thanks for your help!
That's not how class inheritance is supposed to work. You only want to inherit something if the child class is going to make use of a good amount of the attributes/methods within the parent class. If the child class has a markedly different structure it should be a class of its own.
In either case, as mentioned by #jasonharper, at some point you would need to give direction as to which Variable instance belongs in which Model instance, so you're likely to end up with something like these:
varA = Variable(mdl, ...)
# or this
mdl.varA = Variable(...)
With the first way, you would maintain the method on your Variable class:
class Foo:
def __init__(self):
self.vars = []
class Bar:
def __init__(self, foo_instance, **kwargs):
foo_instance.vars.append(self)
f = Foo()
b = Bar(f, hello='hey')
f.vars
# [<__main__.Bar object at 0x03F6B4B0>]
With the second way, you can append the Variable instances into a list each time it's added:
class Foo:
def __init__(self):
self.vars = []
def __setattr__(self, name, val):
self.__dict__.update({name: val})
if not name == 'vars': # to prevent a recursive loop
self.vars.append(val)
f = Foo()
f.vars
# []
f.a = 'bar'
f.vars
# ['bar']
Of course, an easier way would be to just look directly into the __dict__ each time you want vars:
class Bar:
#property
def vars(self):
# Or you can return .items() if you want both the name and the value
return list(self.__dict__.values())
b = Bar()
b.a = 'hello'
b.vars
# ['hello']
Both of these will work the same even if you assigned the attributes with your own class instances.
You can use super() for this and pass the instance to the parent
class Model():
vars = []
def __init__(self, other=None):
if other:
self.vars.append(other)
class Variable(Model):
def __init__(self, a):
self.a = a
super().__init__(self)
mdl = Model()
varA = Variable(3)
varB = Variable(4)
print(mdl.vars)