how to call fucntion which contain nested dictionary from another python script - python-3.x

I am trying to get the nested dictionary data from another python script.
As an example below
main.py
class data():
def __init__(self):
self.result()
def result(self):
self.output_data = {}
def get_list(self):
return self.output_data
--------------------------------------------------------
script.py
from main import data
class communix():
def __init__(self):
def new_data(self):
want to fetch the nested dictionary from get_list function

I made a few modifications in your code, there are some hints I'd like you to note:
In python, use CamelCase naming convention for your class names.
You can mix your two result() and get_list() methods into one method.
Why don't you use inheritence in your second class?
So, regarding points mentionned above, this code worked for me:
main.py
class Data():
def __init__(self):
self.result()
def result(self):
self.output_data = {'data': 'sample data'}
return self.output_data
script.py
from main import Data
class Communix(Data):
def new_data(self):
data_extracted = data_object.result()
return data_extracted
data_object = Communix()
print(data_object.new_data())
output:
>>> {'data': 'sample data'}
I hope it helped you.

Related

Specify class variable in Python to be a numpy array of not yet known size

I have a class like
class MyClass:
def __init__(self):
self.will_be_a_numpy_array = None
def compute():
tmp = receive_data()
self.will_be_a_numpy_array = np.zeros(len(tmp))
# process each item in tmp, save result in corresponding element of self.will_be_a_numpy_array
Here __init__ method is vague regarding the type of self.will_be_a_numpy_array variable. It is unclear to fellow developer or compiler what type of variable should be expected. I cannot initialize variable with self.will_be_a_numpy_array = np.zeros(len(tmp)) because I haven't received data yet. What is the right way to articulate variable type in this case?
You can use the strategy that scikit-learn uses for their estimators, namely, you create the attribute when you receive the data and you use a trailing underscore to warn that this is an attribute that is not created at initialisation:
class MyClass:
def __init__(self):
pass
def process(self, data):
self.data_ = np.array(data)
def is_processed(self):
return hasattr(self, 'data_')

Calling class level variables using "#pytest.mark.parametrize" fixture

I'm trying to iterate a pytest test over a list of values which i generate inside another method in the test class.
The problem is that i get:
"#pytest.mark.parametrize("number",TestScratch.list_testing)
NameError: name 'TestScratch' is not defined" error when i try to run.I know for a fact that when i pass the list as a hard coded list i.e [0,3,54,90] it works.
Below is my code :
class TestScratch(object):
#classmethod
def setup_class(cls):
cls.list_testing = []
#classmethod
def setup_method(cls):
pass
def test_populate_list(self):
for i in range(100):
self.list_testing.append(i)
#pytest.mark.parametrize("number",TestScratch.list_testing)
def test_pytest_param(self, number):
assert type(number) == int
#classmethod
def teardown_class(cls):
'''
pass
'''
I also tried self.class.list_testing
but i get the same error
Environment details:
Python: 3.6.8
Pytest: 5.2.1
You can't use the class in the class definition. As the decorator is read at import time, e. g. while loading the class definition, and not at runtime, the class is not known at this point. You have to define the list outside the class instead:
import pytest
def populate_list():
test_list = []
for i in range(100):
test_list.append(i)
return test_list
list_testing = populate_list()
class TestScratch:
def test_populate_list(self):
# this will fail if list_testing could not be populated
assert len(list_testing) > 50
#pytest.mark.parametrize("number", list_testing)
def test_pytest_param(self, number):
# this will be skipped if list_testing could not be populated
assert type(number) == int
Any parameter you use in a decorator is read only once at load time, so trying to intialize it at runtime won't work. For example here you can find an explanation how parametrization works and why it is not possible to add parameters at runtime.

Pytest object created by object assert_called_once_with

I known how I can test if an injected object was called with a specific argument. But in my case the injected object will create an object that object will create another object and I want to test if that last object was called with the right argument.
in the example below the question would be if c.dirve was called with 100 as argument:
class car:
def drive(self, distance):
print("so fast")
class car_shop:
def buy_car(self):
return car()
class shop_shop:
def buy_shop(self):
return car_shop()
class processor:
def __init__(self, sshop):
self.sshop = sshop
def run(self):
cshop = self.sshop.buy_shop()
c = cshop.buy_car()
c.drive(100)
def main():
sshop = shop_shop()
proc = processor(sshop)
proc.run()
if __name__ == "__main__":
main()
is there a way to test that?
Since this was requested here my approach for testing these objects:
import pytest
from unittest.mock import Mock
from object_returns_object_test_for_arguments import processor, shop_shop
#pytest.fixture
def mock_shop_shop():
return Mock(spec=shop_shop)
def test_processor_car_called_with_100(mock_shop_shop):
proc = processor(mock_shop_shop)
proc.run()
assert mock_shop_shop.car_shop.car.drive.assert_called_once_with(100)
assert mock_shop_shop.car_shop.car.drive.call_count == 1
If using just the code shown in the question, you only have to mock car.drive. This could be done for example this way:
from unittest import mock
from object_returns_object_test_for_arguments import processor, shop_shop
#mock.patch('object_returns_object_test_for_arguments.car.drive')
def test_processor_car_called_with_100(drive_mock):
proc = processor(shop_shop())
proc.run()
drive_mock.assert_called_once_with(100)
As I don't know your real code, you may have to mock more stuff.
As an aside: class names in Python are written upper-case, camelcase-style by default.

Better way than pass the same argument among classes in Python

I have a question related to OOP but it should be implemented in Python.
I have a file user_inputs.py with all the user parameters.
In my main file, I have a function that is called first. This function is responsible to read all the user parameters and return a dictionary that will be used in the rest of the program.
My question is: what is the cleanest way to pass the user_parameters dictionary to all classes? I did it in 2 ways:
Method 1)
def read_user_parameters():
# code to open and read all parameters etc.
return user_parameters # returns a dictionary with all the user parameters
Class A():
def __init__(self, user_parameters):
self.user_parameters = user_parameters
Class B():
def __init__(self, user_parameters):
self.user_parameters = user_parameters
user_parameters = read_user_parameters()
object_A = A(user_parameters)
object_B = B(user_parameters)
I don't like this way because I have dozens of classes that need to pass this argument. So I thought to create a parent class with the user parameters:
Method 2)
Class User_parameters():
def __init__(self, user_parameters):
def read_user_parameters():
# code to open and read all parameters etc.
return user_parameters
Class A(User_parameters):
__init__(self, user_parameters):
super().__init__()
# self.user_parameters comes from the parent class now
Class B(User_parameters):
__init__(self, user_parameters):
super().__init__()
# self.user_parameters comes from the parent class now
object_A = A()
object_B = B()
I prefer method 2, however, when super() is initialized from Class A and Class B the function read_user_parameters() that reads the file will be called twice (multiply this by dozens of times). Is there a better solution than method 1 in which I call read_user_parameters() only once but doesn't need to pass the argument for all classes?
Thank you for your time.
Why not just have a single UserParameters class and two objects of the same class (Also class nameds are supposed to be camel-cases, not snake-cased)
#Single class for user parameters
class UserParameters:
def __init__(self, user_parameters):
self.user_parameters = user_parameters
def read_user_parameters(self):
# code to open and read all parameters etc.
return self.user_parameters
#Two objects
object_A = UserParameters("<params>")
object_B = UserParameters("<params>")

Is there a way to create a mutable list in a class statement? (Python 3x)

So in creating a class, I noticed that I was unable to append any elements for my list in the class. Is there a way to append and arrange the order of elements in the list I create in the class statement?
class Foo():
def __init__(self, bar):
self.__bar = []
def input_method(self):
self.__bar.append()
def return_bar(self)
return self.__bar
candy = Foo()
Is there a way for me to append an element into self.__bar?
You need to actually append something to the list in your appending method:
class Foo():
def __init__(self):
self.__bar = []
def input_method(self, something):
self.__bar.append(something)
def return_bar(self):
return self.__bar
candy = Foo()
Now it seems good to me:
>>> candy.input_method('helloo')
>>> candy.return_bar()
['helloo']
Note that since you weren't using (or sending) the bar argument to the __init__ method, I omitted it from my answer (just warning you)!

Resources