How to check which function has been returned in python? - python-3.x

I have two methods which take different number of arguments. Here are the two functions:
def jumpMX(self,IAS,list):
pass
def addMX(self,IAS):
pass
I am using a function which will return one of these functions to main.I have stored this returned function in a variable named operation.
Since the number of parameters are different for both,how do I identify which function has been returned?
if(operation == jumpMX):
operation(IAS,list)
elif(operation == addMX):
operation(IAS)
What is the syntax for this?Thanks in advance!

You can identify a function through its __name__ attribute:
def foo():
pass
print(foo.__name__)
>>> foo
...or in your case:
operation.__name__ #will return either "jumpMX" or "addMX" depending on what function is stored in operation
Here's a demo you can modify to your needs:
import random #used only for demo purposes
def jumpMX(self,IAS,list):
pass
def addMX(self,IAS):
pass
def FunctionThatWillReturnOneOrTheOtherOfTheTwoFunctionsAbove():
# This will randomly return either jumpMX()
# or addMX to simulate different scenarios
funcs = [jumpMX, addMX]
randomFunc = random.choice(funcs)
return randomFunc
operation = FunctionThatWillReturnOneOrTheOtherOfTheTwoFunctionsAbove()
name = operation.__name__
if(name == "jumpMX"):
operation(IAS,list)
elif(name == "addMX"):
operation(IAS)

You can import those functions and test for equality like with most objects in python.
classes.py
class MyClass:
#staticmethod
def jump(self, ias, _list):
pass
#staticmethod
def add(self, ias):
pass
main.py
from classes import MyClass
myclass_instance = MyClass()
operation = get_op() # your function that returns MyClass.jump or MyClass.add
if operation == MyClass.jump:
operation(myclass_instance, ias, _list)
elif operation == MyClass.add:
operation(myclass_instance, ias)
However, I must emphasize that I don't know what you're trying to accomplish and this seems like a terribly contrived way of doing something like this.
Also, your python code examples are not properly formatted. See the PEP-8 which proposes a standard style-guide for python.

Related

PyTest how to properly mock imported ContextManager class and its function?

This is my sample code:
from path.lib import DBInterface
class MyClass:
def __init__(self):
self.something = "something"
def _my_method(self, some_key, new_setup):
with DBInterface(self.something) as ic:
current_setup = ic.get(some_key)
if current_setup != new_setup:
with DBInterface(self.something) as ic:
ic.set(new_setup)
def public_method(self, some_key, new_setup):
return self._my_method(some_key, new_setup)
(my actual code is bit more complex, but i cant put it here on public :)
Now, what I want to do is, I want to completely mock the imported class DBInterface, because I do not want my unittests to do anything in DB.
BUT I also need the ic.get(some_key) to return some value, or to be more precise, I need to set the value it returns, because thats the point of my unittests, to test if the method behave properly according to value returned from DB.
This is how far I got:
class TestMyClass:
def test_extractor_register(self, mocker):
fake_db = mocker.patch.object('my_path.my_lib.DBInterface')
fake_db.get.return_value = None
# spy_obj = mocker.spy(MyClass, "_my_method")
test_class = MyClass()
# Test new registration in _extractor_register
result = test_class.public_method(Tconf.test_key, Tconf.test_key_setup)
fake_db.assert_has_calls([call().__enter__().get(Tconf.test_key),
call().__enter__().set(Tconf.test_key, Tconf.test_key_setup)])
# spy_obj.assert_called_with(ANY, Tconf.test_key, Tconf.test_key_setup)
assert result.result_status.status_code == Tconf.status_ok.status_code
assert result.result_data == MyMethodResult.new_reg
But i am unable to set return value for call().__enter__().get(Tconf.test_key).
I have been trying many approaches:
fake_db.get.return_value = None
fake_db.__enter__().get.return_value = None
fake_db.__enter__.get = Mock(return_value=None)
mocker.patch.object(MyClass.DBInterface, "get").return_value = None
None of that is actually working and I am running out of options I can think about.
Without having more code or errors that are being produced, it's tough to provide a conclusive answer.
However, if you truly only need to specify a return value for set() I would recommend using MagicMock by virtue of patch --
from unittest.mock import patch
#patch("<MyClassFile>.DBInterface", autospec=True)
def test_extractor_register(mock_db):
mock_db.set.return_value = "some key"
# Rest of test code

how to get pytest fixture return value in autouse mode?

I am new to learn pytest. In bellow sample code.
how can i get A() object in test_one function when fixture is in autouse mode?
import pytest
import time
class A:
def __init__(self):
self.abc = 12
#pytest.fixture(autouse=True)
def test_foo():
print('connecting')
yield A()
print('disconnect')
def test_one():
#how can i get A() object?
print([locals()])
assert 1 == 1
You can always add the fixture as parameter despite the autouse:
def test_one(test_foo):
print(test_foo)
assert 1 == 1
If you don't want to use the fixture parameter for some reason, you have to save the object elsewhere to be able to access it from your test :
a = None
#pytest.fixture(autouse=True)
def test_foo():
global a
a = A()
yield
a = None
def test_one():
print(a)
assert 1 == 1
This could be made a little better if using a test class and put a in a class variable to avoid the use of the global var, but the first variant is still the preferred one, as it localizes the definition of the object.
Apart from that, there is no real point in yielding an object you don't have access to. You may consider if autouse is the right option for your use case. Autouse is often used for stateless setup / teardown.
If your use case is to do some setup/teardown regardless (as suggested by the connect/disconnect comments), and give optional access to an object, this is ok, of course.

Calling various function based on input in python 3.x

I'm writing some code to get various data from a class (which extracts data from a '.csv' file). I was wondering if there was a way to call one of these methods based off the name of an input
I've attempted to create a function called get(), which takes in 'param_name' - the name of the method contained within the class that I want to call. I was wondering if there was a more elegant way to solve this without creating a large amount of if statements.
def get(param_name):
# Some initialisation of the .csv file goes here. This works as intended.
list_of_objects = [] # Initialised above, as a list of objects with methods function1(), function2() for getting data out of the .csv
for item in list_of_objects:
if param_name == "name of function 1":
return function1()
if param_name == "name of function 2":
return function2()
You could store your functions ina a dictionary as such:
function_dict = {
'function_1': function_1,
'function_2': function_2
}
To use these you could do:
function_to_use = function_dict.get(param_name)
function_to_use(*args, **kwargs) # *args, **kwargs are arguments to be used.
If you want to return a list after you have applied the function to all item in list_of_objects instead of the for loop you could do:
list(map(function_to_use, list_of_objects))
You could use __getattribute__:
class Alpha:
def f1(self):
print("F1")
x = Alpha()
x.__getattribute__('f1')()
You can do that using globals(), globals() returns a dict containing all methods and attributes.
def fun1():
print('this is fun1')
def fun2():
print('this is fun2')
def get(func_name):
globals()[func_name]()
get('fun1')
get('fun2')
Will Output:
this is fun1
this is fun2

Python passing parameters as part of the function code

I have 2 functions as follows:
def test1(var):
return var*2
def test2(var):
return var*4
I want to pass a variable to form part of the code, something like below:
var='test2'
def new_test(var,4):
return var(4)
And I expect the output to be 16 (i.e. output from test2)
In excel, it is achievable via the function of =indirect(...). Is there any way to achieve that in Python?
Yes, instead of this:
var = 'test2'
def new_test(var, 4):
return var(4)
You can do this directly:
var = test2
def new_test(var, 4):
return var(4)
Functions are first class objects in Python.

Passing a Function as a Parameter for a Class, eventually turning it into a method

Sorry if the title is confusing. I'm writing a minimalist game engine, and trying to define a class called "Area" where if the player enters the area, a function defined by the user happens. For example, one could create an instance
Area(location,function) that would fire function on the player when the player enters location (for the sake of simplicity, let it be a point or something).
Note: in pseudo-python
# in init.py
...
def function(player):
kill player
deathZone = Area(location,function)
--------------------------------------
# in player.update()
...
for area on screen:
if player in area:
Area.function(player)
The point of this is that the developer (aka me) can use any function they choose for the area. Is there anyway to do this, or should I try a better approach?
Sure, this kind of thing is certainly possible. In python, everything is an object, even a function. So you can pass around a function reference as a variable. For example try the following code:
import math
def rectangle(a, b):
return a*b
def circle(radius):
return math.pi * radius**2
class FunctionRunner(object):
def __init__(self):
self.userFunction = None
self.userParams = None
def setUserFunction(self, func, *params):
self.userFunction = func
self.userParams = params
def runFunction(self):
return self.userFunction(*self.userParams)
if __name__ == '__main__':
functionRunner = FunctionRunner()
functionRunner.setUserFunction(rectangle, 6, 7)
print(functionRunner.runFunction())
functionRunner.setUserFunction(circle, 42)
print(functionRunner.runFunction())
Here you have two functions that are defined for an area, and a class called FunctionRunner which can run any function with any number of input arguments. In the main program, notice that you need only pass the reference to the function name, and any input arguments needed to the setUserFunction method. This kind of thing will allow you to execute arbitrary code on the fly.
Alternatively, you could also replace a method on your class with a reference to another function (which is what you are asking), though this seems less safe to me. But it is certainly possible. For example you could have a class like this:
class FunctionRunner2(object):
def __init__(self):
pass
def setUserFunction(self, func):
self.theFunction = func
def theFunction(self, *params):
pass
And then do this:
if __name__ == '__main__':
functionRunner2 = FunctionRunner2()
functionRunner2.setUserFunction(rectangle)
print(functionRunner2.theFunction(6,7))
functionRunner2.setUserFunction(circle)
print(functionRunner2.theFunction(42))

Resources