Best way to create objects with objects inside - python

I need to create a system of objects which in turn have objects inside, for example:
class A(object):
def __init__(self):
self.A = 'Message from class A'
class B(object):
def __init__(self):
self.B = A()
or do it in this way
class B(object):
def __init__(self):
self.B = A()
class A(object):
def __init__(self):
self.A = 'Message from class A'
so I can't use it like
>>> C = B()
>>> print C.B.A
# Message from class A
what is the best choice of these two, or if there is something else, please welcome!
EDIT 1 current piece of code
class Foam(object):
def __init__(self, rotor, path='OpenFoamCase'):
self.dirs = {}
self.path = path
self.rotor = rotor
self.rotorObj = Rotor(rotor)
# OpenFoam case directories
self.dirs['main'] = path if path.endswith('/') else path + '/'
self.dirs['system'] = path + '/system/'
self.dirs['constant'] = path + '/constant/'
self.dirs['geometry'] = path + '/geometry/'
self.dirs['polyMesh'] = path + '/constant/polyMesh/'
self.dirs['triSurface'] = path + '/constant/triSurface/'
self.__openFoamInit()
self.mesh = OpenFoamBlockMesh(self)
class OpenFoamBlockMesh(object):
def __init__(self, study):
self.airfoil_offset = 0.5
self.rotor_disk_length = [20, 20]
...
def box(self):
...
so now I’m using it as:
study = Foam(rotor=rotor, path='OpenFoamCase_Tesis')
study.mesh.airfoil_offset = 0.02
study.mesh.rotor_disk_length = [2, 2.5]
study.mesh.box()

It really depends on your purpose. If the A class is just a helper class for B, and is a simple and small class, you can use the second method (inner class).
If the class A, might be used for others classes or is a big class, is recommended to use the first method (simple composition).
If you provide a better example of your real world problem, we may be able to help you more.

Related

How to use self in instance variable in python

Its possibly a very silly question and I just do not know how to look for this solution or what to search.
What I was trying is
class X:
def __init__(self, myvariable):
self.myvariable = myvariable
def printVar(self):
print(self.myvariable)
class Z:
aa = 'test'
class Y(Z):
#xx = X(self.aa)
def __init__(self):
self.xx = X(self.aa)
x = Y()
x.xx.printVar()
it works as expected. I was wondering whether its possible to use as
class Y(Z):
xx = X(self.aa)
self only refer to the own context of a class.
You can refer to aa with Z.aa:
class Y(Z):
xx = X(Z.aa)
print(Z.aa)
->
test

Calling an object of a method of a class within another method of the same class

I was trying to call the objects of a method in one of my classes within antoher method of the same class. Below you can find a small example of how I tried to do it:
class example_class():
def some_method(self):
#... calculate something ...
a = 1
b = 2
def second_method(self):
call = self.some_method()
c = call.a + call.b
If I do this, I get the error: "'NoneType' object has no attribute 'a'".
I am sure this is a fearly basic problem, but I am using classes, objects and methods for the first time and would really appreciate the help!
Thank you in advance and stay safe!
class example_class():
def some_method(self):
#... calculate something ...
self.a = 1
self.b = 2
def second_method(self):
# call = self.some_method()
c = self.a + self.b
This should work
class example_class:
def some_method(self):
self.a = 1
self.b = 2
def second_method(self):
self.some_method()
print(self.a + self.b)
You can't access a method's local variables from another method, you should store them as attributes.

Python inheritance: modify a parent class of an object

I need/want to modify a parent class and have problems with proper import. The child object still uses the "old" version of the class.
File A (some lib which I do not want to modify directly):
class A(object):
def __init__(self):
self.contentA = "42"
print("A.__init__() ausgeführt")
def m(self):
print("A.m() aufgerufen")
class B(A):
def __init__(self):
#A.__init__(self)
super().__init__()
self.contentB = "43"
print("B.__init__() ausgeführt")
def m(self):
#A.m(self)
super().m()
print("B.m() aufgerufen")
File B:
import somelib as demo
class A(demo.A):
def __init__(self):
super().__init__()
def f(self):
'''
new function for A!
'''
print("A.f():", self.contentA)
if __name__ == "__main__":
b = demo.B()
b.m()
print("b.contentB: " + str(b.contentB))
print("b.contentA: " + str(b.contentA))
b.f() # not found!
The newly added function f() is not found. How do I have to do this correctly?
Just because your class is also called A this doesn't mean that it will overwrite a previously defined class A in another module. Even if it would, the class B would not depend on it automatically.
Your problem is likely better solved by writing your inherited class B in this module, but if you really want to modify the parent class you can:
import somelib as demo
def f(self):
'''
new function for A!
'''
print("A.f():", self.contentA)
demo.A.f = f # assign f to the f attribute of A
if __name__ == "__main__":
b = demo.B()
b.m()
print("b.contentB: " + str(b.contentB))
print("b.contentA: " + str(b.contentA))
b.f() # found!
Your best bet is probably monkey patching, e.g.:
import somelib as demo
def f(self):
'''
new function for A!
'''
print("A.f():", self.contentA)
demo.A.f = f
if __name__ == "__main__":
b = demo.B()
b.m()
print("b.contentB: " + str(b.contentB))
print("b.contentA: " + str(b.contentA))
b.f() # should now be found!

Modifying library function after importing

Say I'm importing a library which has some core functionality for the program I'm writing. It looks like:
class dothing(object):
def __init__(self):
# stuff
def main(self):
self.thing = []
self.option = []
How can I modify the contents of its variables, without touching the library itself - in other words, from my local code. Or, how can I modify the function "main"?
I've heard of "monkey patching" but I'm not sure this is the right thing
If you want to alter the main function, you can indeed use monkey patching. This is the preferred strategy if you want to alter how the whole class donothing behaves.
class dothing(object):
def __init__(self):
# stuff
def main(self):
self.thing = []
self.option = []
def my_new_main(self):
print("Hello")
self.thing = {}
self.option = ["Foo"]
donothing.main = my_new_main
dn = donothing()
dn.main()
# Hello
dn.thing
# {}
dn.option
# ["Foo"]
You can also use this strategy to attach new methods to donothing.
donothing.bar = lambda self, x: x + 3
dn.bar(1)
# 4
Define another class that inherits from your original class and override the "main" method as follows:
class doOtherThing(dothing):
def main(self):
self.thing = [1] # this is just a value different from [] in the original "main"

confused value scope in python

Hi I have staring programming with c and I conld'nt understand value scope in python.
here is my code
class ScenarioEnvironment():
def __init__(self):
print(self)
class report():
config = ScenarioEnvironment()
def __init__(self):
self.config = ScenarioEnvironment()
what happens passing config and config at init()?
and I wonder the value scope which config will be class valuable?
You need to know the differences between class attribute and instance object attribute.
Maybe these codes will help you:
class TestConfig1(object):
config = 1
def __init__(self):
self.config = 2
class TestConfig2(object):
config = 1
def __init__(self):
self.config2 = 2
if __name__ == "__main__":
print TestConfig1.config
t = TestConfig1()
print t.config
t2 = TestConfig2()
print t2.config
print t2.config2
more you can see the python blog.click here
Since your question seems a bit ambiguous, I'll just comment/fix your code:
class ScenarioEnvironment():
def __init__(self,x):
self.x = x # Assigning instance variable x to constructor parameter x.
print(self) # You're printing the object instance.
class report():
# Static variable shared amongst all classes.
config = ScenarioEnvironment(None) # Assigned to new instance of ScenarioEnvironment.
def __init__(self):
# No argument, must pass one (None).
# self.config is to a new ScenarioEnvironment instance.
self.config = ScenarioEnvironment(None)
Lets try out the classes.
Output:
s = ScenarioEnvironment(None)
r = report()
>>> <__main__.ScenarioEnvironment instance at 0x026F4238>
>>> <__main__.ScenarioEnvironment instance at 0x026F4300>
>>> <__main__.ScenarioEnvironment instance at 0x026F4350>

Categories

Resources