How do I approach this python test? - python

I have a function inside a class, that calls other functions and does some stuff until it obtains two variables, A and B:
Class NumberLogic:
def compare():
#do stuff_
A=#do stuff__
B=#do stuff___
if A<B:
return 1
else:
return 2
I would like to test this function compare() but give values directly from A and B so only the if condition is tested, I am not sure if this is possible and the rest of the code can be mocked so when I call someting like
assert 1 == NumberLogic.compare()

You could rewrite your code like this:
Class NumberLogic:
def compare(self):
A = self._get_A()
B = self._get_B()
return self._compare(A, B)
def _get_A(self):
# do stuff
return A
def _get_B(self):
# do stuff
return B
def _compare(self, A, B):
if A<B:
return 1
else:
return 2
This way you can write your code to check only the _compare
Note: Starting a function with an underscore signifies it's an internal method only used by the function itself.
You could also write:
def _compare(self, A, B):
if A<B:
return 1
return 2
Which is the same thing

Related

nested functions calling with multiple args in python

This was the program for our test and I couldn't understand what is going on. This problem is called nested function problem.
def foo(a):
def bar(b):
def foobar(c):
return a + b + c
return foobar
return bar
a, b, c = map(int,input().split())
res = foo(a)(b)(c)
print(res)
I have tried to debug this program but couldn't get any idea about why it is working.
Why is foo(a)(b)(c) not giving an error?
Why it is working and what it is called?
This is a closures concept, Inner functions are able to access variables of the enclosing scope.
If we do not access any variables from the enclosing scope, they are just ordinary functions with a different scope
def get_add(x):
def add(y):
return x + y
return add
add_function = get_add(10)
print(add_function(5)) # result is 15
Everything in Python is an object, and functions as well, so you can pass them as arguments, return them, for example:
def inc(var):
return var + 1
def my_func():
return inc
my_inc = my_func()
print(my_inc) # <function inc at ...>
print(my_inc(1)) # 2
Moreover it's closed to decorator's concept:
def log_this(func):
def wrapper(*args, **kwargs):
print('start', str(args))
res = func(*args, **kwargs)
return res
return wrapper
#log_this
def inc(var):
return var + 1
print(inc(10))

How do I write a function that satisfies this test?

I need to write a function that satisfies this test in pytest:
def test_return_logger(capsys):
#return_logger
def myfunc(a, b, c):
return a + b + c
val = myfunc(4, 5, 6)
out, err = capsys.readouterr()
assert val == 15
assert "Function returned: 15" in out
Here is what I currently have and it is not working:
def return_logger(f):
def newfunc(s):
original_return_value = f(s)
return f"Function returned: {original_return_value}"
return newfunc
Im honestly completely lost!
Your test wants the function to return the value, and print the string that you were returning.
The newfunc(*args) also solves passing in multiple arguments - they are automatically unpacked when calling the second function.
You probably want this:
def return_logger(f):
def newfunc(*args):
original_return_value = f(*args)
print(f"Function returned: {original_return_value}", sys.stderr)
return original_return_value
return newfunc
Now, when you call the decorated function, it will print Function returned: 15 to stderr and return original_return_value.

Python dispatcher and scenario-specific functions and sub-functions

I am trying to write several functions in Python (dispatcher + scenario-specific functions and sub-functions) as follows:
def dispatcher(event):
if event['name'] == 'func_a':
return func_a(event['data'])
# several elif statements here
elif event['name'] == 'func_n':
return func_n(event['data'])
def func_a(data):
""" multi-scenario function returning dict"""
# Scenario A
if data['certain_param'] == 'certain value':
# do something
# that takes several lines of code
return {'result': 'scenario A'}
# Scenario B
elif data['certain_param'] == 'another value':
# do something else
# that takes several lines of code
return {'result': 'scenario B'}
# some other elif scenarios go here
return {'result': 'Fail'}
# func_b(), func_c(), .... go here (similar to func_a())
def func_n(data):
""" similar logic to funcs a, b, ...."""
pass
I want to break a very long func_a() into several sub-functions (one for each scenario). Here are 2 options:
# makes 2 calls to each scenario sub-function (not ideal)
def func_a(data):
""" same func_a() above"""
# Scenario A
if func_a_scenario_a(data):
return func_a_scenario_a(data)
# other elifs
# Scenario N
elif func_a_scenario_n(data):
return func_a_scenario_n(data)
Yet another way to write func_a() is:
# Not very Pythonic
def func_a(data):
result = func_a_scenario_a(data)
if result:
return result
result = func_a_scenario_b(data)
if result:
return result
# repeat for every scenario
What is (are) better ways to do the above? maybe using eval('some_func()')? or something else? Thanks.
You can create a decorator which can then determine what to pass to its wrapped function. The decorator can store a dictionary with the function name as the key, and an associated value to be passed to the function with the same name as the key:
def dispatcher(f):
registry = {'func_a':"arbitrary_data", 'func_n':"arbitrary_data_1"}
def wrapper(data):
return f(registry[f.__name__])
return wrapper
#dispatcher
def func_a(data):
#do something with data
return
#dispatcher
def func_n(data):
#do something with data
return
func_a("somedata")
func_n("someotherdata") #functions called be called normally

Workaround for equality of nested functions

I have a nested function that I'm using as a callback in pyglet:
def get_stop_function(stop_key):
def stop_on_key(symbol, _):
if symbol == getattr(pyglet.window.key, stop_key):
pyglet.app.exit()
return stop_on_key
pyglet.window.set_handler('on_key_press', get_stop_function('ENTER'))
But then I run into problems later when I need to reference the nested function again:
pyglet.window.remove_handler('on_key_press', get_stop_function('ENTER'))
This doesn't work because of the way python treats functions:
my_stop_function = get_stop_function('ENTER')
my_stop_function is get_stop_function('ENTER') # False
my_stop_function == get_stop_function('ENTER') # False
Thanks to two similar questions I understand what is going on but I'm not sure what the workaround is for my case. I'm looking through the pyglet source code and it looks like pyglet uses equality to find the handler to remove.
So my final question is: how can I override the inner function's __eq__ method (or some other dunder) so that identical nested functions will be equal?
(Another workaround would be to store a reference to the function myself, but that is duplicating pyglet's job, will get messy with many callbacks, and anyways I'm curious about this question!)
Edit: actually, in the questions I linked above, it's explained that methods have value equality but not reference equality. With nested functions, you don't even get value equality, which is all I need.
Edit2: I will probably accept Bi Rico's answer, but does anyone know why the following doesn't work:
def get_stop_function(stop_key):
def stop_on_key(symbol, _):
if symbol == getattr(pyglet.window.key, stop_key):
pyglet.app.exit()
stop_on_key.__name__ = '__stop_on_' + stop_key + '__'
stop_on_key.__eq__ = lambda x: x.__name__ == '__stop_on_' + stop_key + '__'
return stop_on_key
get_stop_function('ENTER') == get_stop_function('ENTER') # False
get_stop_function('ENTER').__eq__(get_stop_function('ENTER')) # True
You could create a class for your stop functions and define your own comparison method.
class StopFunction(object):
def __init__(self, stop_key):
self.stop_key = stop_key
def __call__(self, symbol, _):
if symbol == getattr(pyglet.window.key, self.stop_key):
pyglet.app.exit()
def __eq__(self, other):
try:
return self.stop_key == other.stop_key
except AttributeError:
return False
StopFunciton('ENTER') == StopFunciton('ENTER')
# True
StopFunciton('ENTER') == StopFunciton('FOO')
# False
the solution is to keep a dictionary containing the generated functions around,
so that when you make the second call, you get the same object as in the first call.
That is, simply build some memoization logic, or use one of the libraries
existing with memoizing decorators:
ALL_FUNCTIONS = {}
def get_stop_function(stop_key):
if not stop_key in ALL_FUNCTIONS:
def stop_on_key(symbol, _):
if symbol == getattr(pyglet.window.key, stop_key):
pyglet.app.exit()
ALL_FUNCTIONS[stop_key] = stop_on_key
else:
stop_on_key = ALL_FUNCTIONS[stop_key]
return stop_on_key
You can generalize Bi Rico's solution to allow wrapping any functions up with some particular equality function pretty easily.
The first problem is defining what the equality function should check. I'm guessing for this case, you want the code to be identical (meaning functions created from the same def statement will be equal, but two functions created from character-for-character copies of the def statement will not), and the closures to be equal (meaning that if you call get_stop_function with two equal but non-identical stop_keys the functions will be equal), and nothing else to be relevant. But that's just a guess, and there are many other possibilities.
Then you just wrap a function the same way you'd wrap any other kind of object; just make sure __call__ is one of the things you delegate:
class EqualFunction(object):
def __init__(self, f):
self.f = f
def __eq__(self, other):
return (self.__code__ == other.__code__ and
all(x.cell_contents == y.cell_contents
for x, y in zip(self.__closure__, other.__closure__)))
def __getattr__(self, attr):
return getattr(self.f, attr)
def __call__(self, *args, **kwargs):
return self.f(*args, **kwargs)
If you want to support other dunder methods that aren't required to go through getattr (I don't think any of them are critical for functions, but I could be wrong…), either do it explicitly (as with __call__) or loop over them and add a generic wrapper to the type for each one.
To use the wrapper:
def make_f(i):
def f():
return i
return EqualFunction(f)
f1 = f(0)
f2 = f(0.0)
assert f1 == f2
Or, notice that EqualFunction actually works as a decorator, which may be more readable.
So, for your code:
def get_stop_function(stop_key):
#EqualFunction
def stop_on_key(symbol, _):
if symbol == getattr(pyglet.window.key, stop_key):
pyglet.app.exit()
return stop_on_key

Proper way to quit a function in Python

Assume I have the following ;
def test():
while 1:
a = b
time.sleep(60)
c = b
if(c==a):
do something
then quit the function
What is the proper way to quit from a function having this structure ?
You could just use a return statement.
That would be the most direct way, by just placing the return where you want to quit ("then quit the function").
if(c==a):
do something
return
You could also use this to return any results you have to the calling code.
Eg., return some_results
Python doc for return
Use the return statement: eg
def test():
while 1:
a = b
time.sleep(60)
c = b
if c == a:
print a
return
break would also work, by leaving the while loop.
Just use the return statement to exit the function call.
def blah():
return # Returns None if nothing passed back with it
def blah():
return some_value, some_value2 # Return some values with it if you want.

Categories

Resources