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

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

Related

How to dynamically import the class?

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

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 - Mocking out a function called inside the init of a class using side_effect

I have this class, Foo, whose functions use dataframes I initialize in its constructor. I want to test its functions in my test class, FooTest.
from src.shared.utils import get_spark_dataframe
class Foo(object):
def __init__(self, x, y):
self.a = get_spark_dataframe(x, y.some_db, "table_a")
self.b = get_spark_dataframe(x, y.some_db, "table_b")
def some_foo_function(self):
return self.a.join(self.b, ['pk'])
I want to mock out this get_spark_dataframe function and replace it with my own, since I'm merely interested in replacing the dataframes in the class with fake dataframes I define in my test class.
def get_spark_dataframe(x, db_name, table_name):
return x.get_table(db=db_name, table=table_name).toDF()
This is vaguely what my test class looks like:
class FooTest(PysparkTest):
def setUp(self):
self.a_df = self.spark.createDataFrame([Row(...)])
self.b_df = self.spark.createDataFrame([Row(...)])
self.x = None
self.y = None
def mock_get_spark_dataframe(self, x, db_name, table_name):
if table_name == "table_a":
return self.a_df
elif table_name == "table_b":
return self.b_df
#patch('src.shared.utils.get_spark_dataframe', side_effect=mock_get_spark_dataframe)
def test_some_foo_function(self, mock_get_spark_dataframe):
foo = Foo(self.x, self.y)
return_value = foo.some_foo_function()
...
Am I doing something incorrectly? It doesn't seem like my mock function is being used when I create the Foo object. The real get_spark_dataframe function seems to be getting called, and it complains about x being None. Am I using side_effect incorrectly?
Try these changes in your code:
import src.shared.utils as utils
class Foo(object):
def __init__(self, x, y):
self.a = utils.get_spark_dataframe(x,...
...
and
class FooTest(PysparkTest):
...
#patch('utils.get_spark_dataframe',...
...

Call python object - odoo 9

In python console(jupyter) I use a python library in the form:
class SomeClass(object)
def __init__(self, arg1, arg2):
...
def fct1(self):
...
return something
And I get no problem creating an object with:
x = SomeClass(arg1,arg2)
I would like to use those methods in Odoo.
I tried the following:
class SomeClass(**models.Model**)
def **connect**(self, arg1, arg2):
...
def fct1(self):
...
return something
Replacing "object" with "model,Models" to have it as an odoo class + renaming init with a method name.
But
x = connect(arg1,arg2)
returns :
NameError: global name 'connect' is not defined
How would I use my python library in Odoo (new API)?
TIA
UPDATE:
I also tried calling
x= self.connect(arg1,arg2) or
x=SomeClass.connect(arg1,arg2)
but it return "None" when I "print x". I think an instance is not created
thank you to zbik for the answer:
myclass.py in folder myaddons
class MyClass:
def __init__(self, name):
self.name = name
def _test(self,a,b):
return a+b
in other Odoo class:
from openerp.addons.myaddons.myclass import MyClass
...
x = MyClass('Hello')
y = x._test(2,3)
...
print x.name
> Hello
print y
> 5

How to always use the same instance of a class in Python?

I am using the following solution to maintain a list of classes instances: https://stackoverflow.com/a/12102163
Now I want to use that list to make sure that there is always only one instance of the class. Renewed initializations of the class should return the one existing instance.
The code I have is:
class MyClass:
instances = []
def __init__(self):
if not MyClass.instances:
self.data=1234
else:
self = MyClass.instances[0]
So:
>> a=MyClass()
>> a.data
1234
And b=MyClass() should return the same instance as a. This is not working. What is wrong with my code?
EDIT: OK, so it turns out I am looking for the singleton pattern, but couldn't recreate it myself. Can anyone please explain why my code does not work?
Going on your code line and your style. You can make following modifications:-
class MyClass:
instance = None
def __init__(self):
self.data=1234
MyClass.instance = self
def get_myclass():
if MyClass.instance:
return MyClass.instance
return MyClass()
get_myclass would be a wrapper function for creating class objects. Trying the code.
>>> import instance
>>> a=instance.get_myclass()
>>> b=instance.get_myclass()
>>> a is b
True
Here's an example of the Singleton metaclass recipe. This example is from Ch. 9 of The Python Cookbook.
class Singleton(type):
def __init__(self, *args, **kwargs):
self.__instance = None
super().__init__(*args, **kwargs)
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super().__call__(*args, **kwargs)
return self.__instance
else:
return self.__instance
# Example
class Spam(metaclass=Singleton):
def __init__(self):
print('Creating Spam')
if __name__ == '__main__':
a = Spam()
b = Spam()
assert a is b
There's actually a quite simple solution to use the same instance of a class in Python. Here's a demo example:
#### module1.py ####
class MyClass1:
...
# Create an instance of the class in the same module!
my_class_1 = MyClass1()
#############################################################################
#############################################################################
#### module2.py ####
# Here import the instance (not the class!) from module1
from module1 import my_class_1
class MyClass2:
# Do stuff to my_class_1
...
#############################################################################
#############################################################################
#### module3.py ####
# Here also import the instance (not the class!) from module1
from module1 import my_class_1
class MyClass3:
# Also do stuff to my_class_1
...
In the example above, no matter which module (whether module2.py or module3.py) changes data of the my_class_1 instance, the changed data is reflected in both modules synchronously.

Categories

Resources