How to dynamically import the class? - python

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

Related

How to pass variable value through classes in different files?

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)

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!

Base class variable does not store value which is set by Derived class

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 == ''

Make Python module classes able to be called from a separate class

I currently have a module, my_module, which contains classes.py:
from . import config
class Class1:
#staticmethod
def method_one(x)
return x + config.constant
#staticmethod
def method_two(y)
return x - config.constant
My problem is that I want to be able to have multiple instances of the module with different values for config.constant. Ideally, I'd have a new class called MyClass where the constant would be an instance variable, so that this would work:
instance1 = MyClass(5)
instance1.Class1.method_one(5) # 10
instance2 = MyClass(0)
instance2.Class1.method_one(5) # 5
Is there a way to do this without modifying the classes which are in my_module?
Make it a staticmethod.
class MyClass(object):
#staticmethod
def my_method(num):
return num + num
Then you can use it from another file by doing(assuming the file is my_module.py:
import my_module
my_module.MyClass.my_method(2)
>>>4
my_module.py
def __init__(self, constant):
self.constant = constant
def my_method(self, num):
return self.constant + num
some_other_file.py
import my_module
MyClass = type('MyClass', (), my_module.__dict__)
my_instance = MyClass(3)
my_instance.my_method(4)
>>> 7

python className not defined NameError

I have a class which i need to instantiate in order to call a method that it contains. When I access it from another class it works fine but when i run from terminal it says :
File "myClass.py", line 5, in <module>
class MyClass:
File "myClass.py", line 23, in ToDict
td=MyClass()
NameError: name 'MyClass' is not defined
Pasting the code:
class MyClass:
def convert(self, fl):
xpD = {}
# process some stuff
return xpD
if __name__ == "__main__":
source = sys.argv[1]
td = MyClass()
needed_stuff = td.convert(source)
print(needed_stuff)
The problem is that your if __name__ == "__main__" block is inside of your class definition. This will cause an error, as the code within the if will be run as part of the class being created, before the class been bound to a name.
Here's a simpler example of this error:
class Foo(object):
foo = Foo() # raises NameError because the name Foo isn't bound yet
If you format your code like this (that is, with the if unindented at the top level), it should work correctly:
class MyClass:
def convert(self, fl):
xpD = {}
# process some stuff
return xpD
if __name__ == "__main__":
source = sys.argv[1]
td = MyClass()
needed_stuff = td.convert(source)
print(needed_stuff)

Categories

Resources