How do I write a function that satisfies this test? - python

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.

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 to obtain tuple values from inside of decorator functions in Python

I am exploring decorator functions in Python. My objective is to return a tuple from a wrapper function inside of the decorator function, when the original function that is passed to the decorator functin also returns a tuple. My code snippet is pasted below:
def decorator_function(original_function):
def wrapper_function(*args, **kwargs):
s, o = original_function(*args, **kwargs)
return s, o
return wrapper_function
def test_function(name, command):
status = True
output = dict()
output['message'] = command + " " + name
return status, output
decorator_func_var = decorator_function(test_function("Kaushik", "Hello"))
ok, out = decorator_func_var()
print(ok)
print(out)
However, when I execute this, I get an error message as follows:
I am curious to know where I am going wrong with my code snippet and how can I obtain the tuple values when calling a decorated function. I would really appreciate any suggestions or feedback.
Your decorator takes a function as an argument, and returns a function. You just want
ok, out = decorator_function(test_function)("Kaushik", "Hello")
or a little bit more clearly:
wrapped_function = decorator_function(test_function)
ok, out = wrapped_function("Kaushik", "Hello")
def decorator_function(original_function):
def wrapper_function(*args, **kwargs):
s, o = original_function(*args, **kwargs)
return s, o
return wrapper_function
def test_function(name, command):
status = True
output = dict()
output['message'] = command + " " + name
return status, output
decorator_func_var = decorator_function(test_function)
ok, out = decorator_func_var("Kaushik", "Hello")
print(ok)
print(out)
You pass the parameters after initialising decorator_func_var

Wrapping a Python function that uses with

Say have a python function foo() that uses some resource and is meant to be called as follows:
with foo(x,y,z) as f:
doSomething(f)
So far so good. Now lets say foo takes in a complex set of arguments based on a variety of factors, and I'd like to define a wrapper function to make things simpler. Something like:
def simple_foo():
if x:
return foo(a,b,c)
else:
return foo(d,e,f)
Now, I'd like to use simple_foo in place of foo, like:
with simple_foo() as f:
doSomething(f)
However, unsurprisingly, this does not work. How can I write simple_foo() to get this behavior?
Decorate function foo() with contextmanager (doc):
from contextlib import contextmanager
#contextmanager
def foo(a, b, c):
try:
yield a + b + c
finally:
pass
def simple_foo(x):
if x:
return foo(1, 2, 3)
return foo(4, 5, 6)
with simple_foo(True) as v:
print(v)
with simple_foo(False) as v:
print(v)
Prints:
6
15
You can do by writing a custom context manager that internally calls that function, try code given below:
class SimpleFoo:
def __init__(self,x,y,z, option):
self.x = x
self.y = y
self.z = z
self.option = option
def __enter__(self):
if self.option:
return foo(self.x,self.y,self.z)
else:
return foo(self.y,self.z,self.x)
def __exit__(self, type, value, traceback):
if type != None:
print("Error in SimpleFoo")
print("Error Type :", type)
print("Error Value :", value)
print("Error Traceback :", traceback)
self.status = value
Now if you want to use this, use it as below:
with SimpleFoo(1,2,3,True) as foo:
doSomething(foo)
I hope this helps.

Is there any way to execute a statement before each return statement in python function?

For example i have this piece of code:
def example():
a = 'goodbye'
if True:
print a
return 1
else:
print a
return 0
I would like to know if there is any possible solution to write once "print a" and execute it before each "return" statement automaticaly. So that if I add more return statements I wouldn't need to add anything, but "print a" would execute. Result would look like something:
def example():
a = "goodbye"
""" some code to implement print a """
if True:
return 1
else:
return 0
Each time there is return statement it still would print a.
I tried to google, but don't know how word query, since all results are about returning multiple values.
UPDATE: My question was answered, thanks to all of you.
Although wrapping functions are correct answer, but I have chosen answer by GingerPlusPlus who suggested to use try...finally for simplicity.
try .. finally:
def example():
try:
if True:
return 1
else:
return 0
finally:
print 'goodbye'
>>> example()
goodbye
1
A finally clause is always executed before leaving the try statement, whether an exception has occurred or not. Docs
You can use a context. Initialize it with the value you want to print. Then print when context exit, i.e. upon return.
class PrinterOnContextExit():
def __init__( self, a ): self.a = a
def __enter__( self ): pass
def __exit__( self, exc_type, exc_value, traceback ): print( self.a )
def example():
a = 'goodbye'
with PrinterOnContextExit( a ):
if True:
return 1
else:
return 0
Note that you cannot print the returned value this way. If you ever wanted to print the returned value, then you should use a decorator.
class PrintOnReturn():
def __init__( self, a ): self.a = a
def __call__( self, func ): return lambda *args, **kwargs: self.callFunc( func, *args, **kwargs )
def callFunc( self, func, *args, **kwargs ): r = func( *args, **kwargs ); print( self.a, r ); return r
#PrintOnReturn( "hello" )
def example():
if True:
return 1
else:
return 0
This will print whatever string you passed to the decorator, followed by the value returned from the decorated function. Here hello 1.
Code:
def example():
a = 'goodbye'
print a
if True:
return 1
else:
return 0
If you print a before if else then it will print value every time you call the function.
You could also use a decorator, if it suits your case:
>>> def decorator(text):
... def wrapped(func):
... def inner(*args, **kwargs):
... result = func(*args, **kwargs)
... print text
... return result
... return inner
... return wrapped
...
>>> #decorator('goodbye')
... def example():
... return True
...
>>> example()
goodbye
>>> True
Decorator will allow you to print any text after the decorated function was called. Or before.
Create a value returnval
returnval = 0 #default value
testval = 0 # Code to set up if
# code to set various values of testval
if testval == 0:
returnval = 1
elif testval == 5:
returnval = 2
else:
returnval = 10
print a
return returnval
Def example():
a = 'goodbye'
if True:
return 1,str(a)
else:
return 0,str(a)
print example()
Thats the only way...I dont think there is a way to avoid typing what you want to be printed...sorry mate! expect if you type a function type the thinks you
An easier alternative as i've also posted here for a similar topic:
def master_example():
a = []
def example():
a.append('goodbye')
if True:
return 1
else:
return 0
example()
print a[0]

How to use Python decorators to check function arguments?

I would like to define some generic decorators to check arguments before calling some functions.
Something like:
#checkArguments(types = ['int', 'float'])
def myFunction(thisVarIsAnInt, thisVarIsAFloat)
''' Here my code '''
pass
Side notes:
Type checking is just here to show an example
I'm using Python 2.7 but Python 3.0 whould be interesting too
EDIT 2021: funny that type checking did not go antipythonic in the long run with type hinting and mypy.
From the Decorators for Functions and Methods:
Python 2
def accepts(*types):
def check_accepts(f):
assert len(types) == f.func_code.co_argcount
def new_f(*args, **kwds):
for (a, t) in zip(args, types):
assert isinstance(a, t), \
"arg %r does not match %s" % (a,t)
return f(*args, **kwds)
new_f.func_name = f.func_name
return new_f
return check_accepts
Python 3
In Python 3 func_code has changed to __code__ and func_name has changed to __name__.
def accepts(*types):
def check_accepts(f):
assert len(types) == f.__code__.co_argcount
def new_f(*args, **kwds):
for (a, t) in zip(args, types):
assert isinstance(a, t), \
"arg %r does not match %s" % (a,t)
return f(*args, **kwds)
new_f.__name__ = f.__name__
return new_f
return check_accepts
Usage:
#accepts(int, (int,float))
def func(arg1, arg2):
return arg1 * arg2
func(3, 2) # -> 6
func('3', 2) # -> AssertionError: arg '3' does not match <type 'int'>
arg2 can be either int or float
On Python 3.3, you can use function annotations and inspect:
import inspect
def validate(f):
def wrapper(*args):
fname = f.__name__
fsig = inspect.signature(f)
vars = ', '.join('{}={}'.format(*pair) for pair in zip(fsig.parameters, args))
params={k:v for k,v in zip(fsig.parameters, args)}
print('wrapped call to {}({})'.format(fname, params))
for k, v in fsig.parameters.items():
p=params[k]
msg='call to {}({}): {} failed {})'.format(fname, vars, k, v.annotation.__name__)
assert v.annotation(params[k]), msg
ret = f(*args)
print(' returning {} with annotation: "{}"'.format(ret, fsig.return_annotation))
return ret
return wrapper
#validate
def xXy(x: lambda _x: 10<_x<100, y: lambda _y: isinstance(_y,float)) -> ('x times y','in X and Y units'):
return x*y
xy = xXy(10,3)
print(xy)
If there is a validation error, prints:
AssertionError: call to xXy(x=12, y=3): y failed <lambda>)
If there is not a validation error, prints:
wrapped call to xXy({'y': 3.0, 'x': 12})
returning 36.0 with annotation: "('x times y', 'in X and Y units')"
You can use a function rather than a lambda to get a name in the assertion failure.
As you certainly know, it's not pythonic to reject an argument only based on its type.
Pythonic approach is rather "try to deal with it first"
That's why I would rather do a decorator to convert the arguments
def enforce(*types):
def decorator(f):
def new_f(*args, **kwds):
#we need to convert args into something mutable
newargs = []
for (a, t) in zip(args, types):
newargs.append( t(a)) #feel free to have more elaborated convertion
return f(*newargs, **kwds)
return new_f
return decorator
This way, your function is fed with the type you expect
But if the parameter can quack like a float, it is accepted
#enforce(int, float)
def func(arg1, arg2):
return arg1 * arg2
print (func(3, 2)) # -> 6.0
print (func('3', 2)) # -> 6.0
print (func('three', 2)) # -> ValueError: invalid literal for int() with base 10: 'three'
I use this trick (with proper conversion method) to deal with vectors.
Many methods I write expect MyVector class as it has plenty of functionalities; but sometime you just want to write
transpose ((2,4))
The package typeguard provides a decorator for this, it reads the type information from type annotations, it requires Python >=3.5.2 though. I think the resulting code is quite nice.
#typeguard.typechecked
def my_function(this_var_is_an_int: int, this_var_is_a_float: float)
''' Here my code '''
pass
To enforce string arguments to a parser that would throw cryptic errors when provided with non-string input, I wrote the following, which tries to avoid allocation and function calls:
from functools import wraps
def argtype(**decls):
"""Decorator to check argument types.
Usage:
#argtype(name=str, text=str)
def parse_rule(name, text): ...
"""
def decorator(func):
code = func.func_code
fname = func.func_name
names = code.co_varnames[:code.co_argcount]
#wraps(func)
def decorated(*args,**kwargs):
for argname, argtype in decls.iteritems():
try:
argval = args[names.index(argname)]
except ValueError:
argval = kwargs.get(argname)
if argval is None:
raise TypeError("%s(...): arg '%s' is null"
% (fname, argname))
if not isinstance(argval, argtype):
raise TypeError("%s(...): arg '%s': type is %s, must be %s"
% (fname, argname, type(argval), argtype))
return func(*args,**kwargs)
return decorated
return decorator
I have a slightly improved version of #jbouwmans sollution, using python decorator module, which makes the decorator fully transparent and keeps not only signature but also docstrings in place and might be the most elegant way of using decorators
from decorator import decorator
def check_args(**decls):
"""Decorator to check argument types.
Usage:
#check_args(name=str, text=str)
def parse_rule(name, text): ...
"""
#decorator
def wrapper(func, *args, **kwargs):
code = func.func_code
fname = func.func_name
names = code.co_varnames[:code.co_argcount]
for argname, argtype in decls.iteritems():
try:
argval = args[names.index(argname)]
except IndexError:
argval = kwargs.get(argname)
if argval is None:
raise TypeError("%s(...): arg '%s' is null"
% (fname, argname))
if not isinstance(argval, argtype):
raise TypeError("%s(...): arg '%s': type is %s, must be %s"
% (fname, argname, type(argval), argtype))
return func(*args, **kwargs)
return wrapper
I think the Python 3.5 answer to this question is beartype. As explained in this post it comes with handy features. Your code would then look like this
from beartype import beartype
#beartype
def sprint(s: str) -> None:
print(s)
and results in
>>> sprint("s")
s
>>> sprint(3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 13, in func_beartyped
TypeError: sprint() parameter s=3 not of <class 'str'>
All of these posts seem out of date - pint now provides this functionality built in. See here. Copied here for posterity:
Checking dimensionality When you want pint quantities to be used as
inputs to your functions, pint provides a wrapper to ensure units are
of correct type - or more precisely, they match the expected
dimensionality of the physical quantity.
Similar to wraps(), you can pass None to skip checking of some
parameters, but the return parameter type is not checked.
>>> mypp = ureg.check('[length]')(pendulum_period)
In the decorator format:
>>> #ureg.check('[length]')
... def pendulum_period(length):
... return 2*math.pi*math.sqrt(length/G)
you could try with the pydantic validation_decorator. from the documentation pydantic:
Data validation and settings management using python type annotations.
pydantic enforces type hints at runtime, and provides user friendly
errors when data is invalid.
In benchmarks pydantic is faster than all other tested libraries.
from pydantic import validate_arguments, ValidationError
#validate_arguments
def repeat(s: str, count: int, *, separator: bytes = b'') -> bytes:
b = s.encode()
return separator.join(b for _ in range(count))
a = repeat('hello', 3)
print(a)
#> b'hellohellohello'
b = repeat('x', '4', separator=' ')
print(b)
#> b'x x x x'
try:
c = repeat('hello', 'wrong')
except ValidationError as exc:
print(exc)
"""
1 validation error for Repeat
count
value is not a valid integer (type=type_error.integer)
"""
For me, the codes shared above looks complicated. What I did for defining 'generic decorator' for type-check:
I used *args, **kwargs feature, little extra work when using function/method but easy to manage.
Appropriate example definition for test
argument_types = {
'name':str,
'count':int,
'value':float
}
Decoration Defination
//from functools import wraps
def azure_type(func):
#wraps(func)
def type_decorator(*args, **kwargs):
for key, value in kwargs.items():
if key in argument_types:
if type(value) != argument_types[key]:
#enter code here
return 'Error Message or what ever you like to do'
return func(*args, **kwargs)
return type_decorator
Simple sample in code
// all other definitions
#azure_type
def stt(name:str, value:float)->(int):
#some calculation and creation of int output
count_output = #something int
return count_output
// call the function:
stt(name='ati', value=32.90) #can test from that

Categories

Resources