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!
Related
Let say I have function a() which is called in many places and I am not able to trace it or change it.
I need some replacement of this function, with calls to it and also do some additional staff.
The old code has many calls a() function so I need some redefinition a=b.
However, example below cause infinite recursion
def a():
return "hello" #do not edit!
def b():
prefix = a() # get something from a
return prefix+" world"
a=b
#...somewhere
a()
Is there any possibility to do this?
You do it with monkey-patching, by using a different variable to hold the old definition.
original_a = a
def b():
prefix = original_a()
return prefix + " world"
a = b
use inheritance
class a:
value=9
def __init__(self):
print("I'm a parent")
def fnc():
print("parent fnc")
class b(a):
def __init__(self):
#super().__init__()
print("I'm a child!")
#classmethod
def fnc(cls):
super().fnc()
print("child fnc")
#classmethod
def getValue(cls):
return super().value
output:
I'm a child!
parent fnc
child fnc
9
make a the Parent and b the SuperChild
b can now access the methods and attributes of a
your wrapping b with the functionality of a
I have four files: main.py, MainClass.py, SigClass.py, and MyClassC.py. The entry is main.py. I rewrite the function function_a of MyClassA in MyClassC, so I need to set SigClass in main.py sig attribute, so MainClass inherits MyclassC and MyclassA in MainClass.py. My code is as follows, which does not inherit the function function_a of MyClassC.
This question explains why the weird class in the middle is used.
I have tried many methods, but I can only achieve my goal in TempClass in the main() space of MainClass.py, but in __main__ of MainClass.py Space can't do it.
How can the TempClass in the main() space be referenced in other files? I really can’t think of a way.
How can I modify the code? Or is there any other way?
The sample code is as follows:
main.py:
from MainClass import SigClass, main
SigClass.sig = "MyClassC"
main()
from MainClass import MainClass
MainClass.function_a()
print(MainClass.property)
MainClass.py:
from time import time
from SigClass import SigClass
import importlib
sig = SigClass.sig
class MyClassA:
sig = '1'
property = 'A'
#classmethod
def function_a(cls):
cls.property = 'A'
class MainClass:
pass
def main():
module_name = SigClass.sig
class_name = SigClass.sig
module_object = importlib.import_module(module_name)
module_class_object = getattr(module_object, class_name)
class TempClass(module_class_object, MyClassA):
pass
global MainClass
MainClass = TempClass
SigClass.py
class SigClass:
sig = 1
MyClassC.py
from MainClass import MyClassA
class MyClassC(MyClassA):
#classmethod
def function_a(cls):
cls.property = 'c'
pass
Thanks to #2e0byo's tips, I think the following code best meets my needs:
Import MyClassC according to SigClass.sig, and SigClass.sig is also the most important part of MainClass.
class BaseClass:
name = None
pass
class SigClass(BaseClass):
name = "SigClass"
sig = 1
class MyClassA(BaseClass):
name = "MyClassA"
property = 'A'
sig = 'a'
#classmethod
def function_a(cls):
pass
class MyClassC(MyClassA):
name = "MyClassC"
property = "C"
sig = 'c'
#classmethod
def function_a(cls):
pass
class ClassCollections(BaseClass):
classes: dict = {}
#classmethod
def add_class(cls, class_to_add: type(BaseClass)):
cls.classes[class_to_add.name] = class_to_add
SigClass.sig = "MyClassC"
ClassCollections.add_class(MyClassA)
ClassCollections.add_class(MyClassC)
class MainClass(SigClass, ClassCollections.classes[SigClass.sig], MyClassA):
pass
print(MainClass.sig)
MyClassC
I have this problem.
I need to pass an "a" variable processed in an execute () method in a class A
To an execute () method located in a class B in a different file.
below my code:
fileA.py
a = 0
class A:
def execute(self):
global a
a = 10
fileB.py
from fileA import A
class B:
def execute(self):
b = a
print (b)
main.py
from fileA import A
from fileB import B
if __name__== "__main__":
first = A()
first.execute()
second = B()
second.execute()
If i try this i get an error:
AttributeError: type object 'A' has no attribute 'a'
How can I make that the value of the variable "a" (elaborated in method of class A) is also seen inside a method of class B ?
Thanks in advance
You'd better do something like this:
fileA.py
class A():
def __init__(self, a=0):
self.a = a
def execute(self):
self.a = 10
fileB.py
class B():
def __init__(self, class_a, b=0):
self.class_a = class_a
self.b = b
def execute(self):
self.b = self.class_a.a
print(self.b)
main.py
from fileA import A
from fileB import B
if __name__== "__main__":
first = A()
first.execute()
second = B(first)
second.execute()
you can skip the init part for self.a and self.b but it's much better to keep it
Use composition.
In module_a:
class A:
a = 0
def set_a(self):
self.a = 10
In module_b:
from module_a import A
class B:
a = A()
def execute(self):
print(a.a)
if __name__ == "__main__":
b = B()
b.a.set_a()
b.execute()
I think that there is a misunderstanding about global and import.
import is reponsible for 2 different things:
the module is loaded into the sys.modules list and executed
the identifiers are made available in current scope
global only says that the referenced variables should be searched only in module scope and skip any local scope.
Now what happens.
fileA declares a class (A) and a variable (a). And class A only contains an execute method and no other attribute. A.execute just happens to set the value of the module level a variable.
fileB imports the class A from fileA, but not the module level variable a. But it uses a variable a in the B.execute method, while it has never been declared neither in module scope nor in local one, hence the error.
How to fix:
At the simplest level, you could import into fileB module the variable a (that you use) instead of the class A that you do not:
fileB.py
from fileA import a
class B:
def execute(self):
b = a
print (b)
I am new to python.
Base class/python file(Base.py).
SESSION_ID = ""
def m1():
print "SESSION_ID in base: ",SESSION_ID
Derived class(Derived.py)
from Base import *
class Derived():
def m2(self):
global SESSION_ID
SESSION_ID = 10
print "SESSION_ID in derived: ", SESSION_ID
def main():
c2 = Derived()
c2.m2()
m1()
if __name__ == "__main__":
main()
When I execute Derived.py file below is the output:
SESSION_ID in derived: 10
SESSION_ID in base:
I want the value which is set in m2() to be reflected in m1(). So the expected output is:
SESSION_ID in derived: 10
SESSION_ID in base: 10
Can you please help?
The global variable in a module is merely an attribute (i.e. a member
entity) of that module.
As result of that when you use import *, the new local module global SESSION_ID is created, so the SESSION_ID in the base is immune to the changes you are doing in the Derived.
Basically, modifying base.SESSION_ID don't require usage of the global statement in the Derived.py, adjusting import is enough, see code below:
from settings import base
class Derived():
def m2(self):
base.SESSION_ID = 10
print "SESSION_ID in derived: ", base.SESSION_ID
def main():
c2 = Derived()
c2.m2()
base.m1()
if __name__ == "__main__":
main()
Your Derived class is not derived from anything inside Base.py. Here, you are just calling a basic function from Base from within Derived, nothing more.
Here is an example on class inheritance in Python3 :
>>> class Base():
>>> SESSION = 42
>>>
>>> def print_session(self):
>>> print("Base session : %d" % self.SESSION)
>>>
>>> class Derived(Base):
>>> SESSION = 999
>>>
>>> d = Derived()
>>> d.print_session()
Base session : 999
I would avoid using global and class-scoped variables if at all possible. These can make your program harder to understand (if something else changes a global underneath you it's hard to notice) and test (you need to reset all global state between every test; it's often easier to just create new empty state).
I might restructure this example by creating a state object:
class State:
def __init__(self):
self.session_id = ''
And then making that explicitly be a property, say, of the base class:
class Base:
def __init__(self, state):
self.state = state
def m1(self):
print("SESSION_ID in base: " + str(self.state.session_id))
class Derived(Base):
def m2(self):
self.state.session_id = '10'
print("SESSION_ID in derived: " + str(self.state.session_id))
Then in your main function you need to explicitly create the state object and pass it in
def main():
state = State()
c2 = Derived(state)
c2.m2()
c2.m1()
But, critically, your tests don't need to worry about state leakage
def test_m2():
state = State()
obj = Derived(state)
obj.m2()
assert state.session_id == '10'
def test_m1():
state = State()
obj = Base(state)
obj.m1()
# If the session ID was a global or a class variable,
# you'd get a different result if m2() was called or not
assert state.session_id == ''
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.