Default value of python get function [duplicate] - python

This question already has answers here:
dict.get() - default arg evaluated even upon success
(6 answers)
Closed 2 years ago.
If the default value passed to python get function (for dictionaries) is an expression, is it evaluated only when the key is not found? Let's consider the following example.
myDiction = {"a":1,"b":2}
val = myDiction.get("c",pow(2,3)-5)
Is that math expression pow(2,3)-5 evaluated or not?

It's not hard to test by passing your own function.
def someF():
print("called")
return 3
myDiction = {"a":1,"b":2}
myDiction.get("a",someF())
Prints: "called". So yes it is evaluated, like you would expect from any argument passed to to a function.

Why don't we find out?
>>> d = {1:2}
>>> d.get(1, print('default') or 3)
default
2
>>> d.get(2, print('default') or 3)
default
3
As you can see, function arguments are evaluated before being passed to the function.

It will be evaluated anyway.
Try this:
def test_func():
print("run")
return 3
myDiction = {"a": 1, "b": 2}
val = myDiction.get("a", test_func())
print(val)
You can see that even though a exists in the myDiction, the "run" message is printed.

I've been wishing for a "lazy" version of dict.get that would allow passing a callable which will be called only if the key is missing a very long time now.
We don't have it yet, but one can implement that quite easily.
from collections import UserDict
def lazy_default_func():
print('in lazy_default_func')
return 7
def lazy_default_func_with_args(*args, **kwargs):
print('in lazy_default_func_with_args', 'args', args, 'kwargs', kwargs)
return 7
class MyDict(UserDict):
def get(self, item, default=None, *args, **kwargs):
print('in get')
if item in self:
return self[item]
if not callable(default):
return default
return default(*args, **kwargs)
d = MyDict({'a': 1})
print(d.get('a', lazy_default_func))
print(d.get('b', lazy_default_func))
print(d.get('b', lazy_default_func_with_args, 'arg1'))
outputs
in get
1
in get
in lazy_default_func
7
in get
in lazy_default_func_with_args args ('arg1',) kwargs {}
7

Related

How to call multiple functions as arguments inside another function? [duplicate]

This question already has answers here:
passing functions and its arguments to another function
(3 answers)
Closed 5 years ago.
I am struggling with the below exercise:
Arguments to particular functions should be passed to function_results_sum as keywords argumentsand it should look like FUNCTION_NAME=ARGUMENTS
The function_results_sum should return sum of all the results received after running each passing function with arguments
If the function has no arguments, the arguments shouldn't be passed to function_results_sum
If the function takes 1 argument, as keyword argument int will be passed to function_results_sum (for example one_arg_function_name=2)
If function takes more than 1 argument - tuple is expected to be passed (for example two_args_function_name=(1, 2) )
How it should work like:
1st example
functions signatures:
def no_arg()
def one_arg(a)
def multiple_args(a, b, c, e, f)
calling function_results_sum:
function_results_sum(
no_arg, one_arg, multiple_args,
one_arg=23,
multiple_args=(1, 2, 3, 4, 5)
)
2nd example of how to call function_results_sum:
function_results_sum(
no_arg, one_arg, multiple_args,
one_arg=-1245,
multiple_args=(45, 65, 76, 123456, 111.222)
)
! Use name attribute on the function object !
This is what I came up with, however I do not know why I get the result as the addresses of the cells where the outputs are stored:
Console output:
<function ident at 0x00000288C0A72048> <function no_arg at
0x00000288C0A6BF28>
<function mult at 0x00000288C0A720D0>
My implementation:
def function_results_sum(*args, **kwargs):
return [*args]
def no_arg():
return 5
def ident(x):
return x
def mult(x, y):
return x * y
a = function_results_sum(ident, no_arg, mult, ident = 2, mult = (2, 3))
print(a)
Here's a hint that calls the one-argument function:
def function_results_sum(*args, **kwargs):
func = args[0]
function_name = func.__name__
parameter = kwargs[function_name]
return func(parameter)
def ident(x):
return x
a = function_results_sum(ident,ident=2)
print(a)
args will contain a list of the functions to be called, and kwargs contains the list of parameters using the function names as keys. See if you can figure out how to call the three types of functions.

python call a function with kwargs

I have a function:
def myfunc():
kwargs = {}
a = 1
b = 2
kwargs.update(a=a, b=b)
newfunc(**kwargs)
and my newfunc
def newfunc(**kwargs):
print a
Its not giving the value of a which is 1
whats wrong ?
It's because you didn't put any key, value in your dictionary, you should have written that :
def newfunc(**kwargs):
print kwargs["a"]
def myfunc():
kwargs = {"a" :1, "b": 2}
newfunc(**kwargs)
You can refer to this thread to understand kwargs better : Understanding kwargs in Python
You should add yor variables to your dictionary and print the item at position of the variable. To me it looks like your code should be written as:
def myfunc():
kwargs = {'a': 1,
'b': 2}
newfunc(**kwargs)
def newfunc(**kwargs):
print(kwargs['a'])
if(__name__ == '__main__'):
myfunc()
or your newfunc should have the arguments you want to fill with your kwargs dictionary like:
def myfunc():
kwargs = {'a': 1,
'b': 2}
newfunc(**kwargs)
def newfunc(a, b):
print(a)
if(__name__ == '__main__'):
myfunc()
Hope that helps.
You forgot to include the error. The Error would have been a NameError, a being undefined.
There's multiple things wrong with your code:
def myfunc():
kwargs = {}
a = 1
b = 2
this doesn't change the dictionary kwargs. This just created two new local names a and b. I guess what you wanted to have is:
kwargs = {}
kwargs["a"] = 1
kwargs["b"] = 2
EDIT: Your update does solve the issue above this line
Then:
def newfunc(**kwargs):
print a
Will give you an Error, because where should a come from?
Using **kwargs here just tells python to store all (not previously absorbed) arguments get stored in a new dictionary. What you hence want is either something like:
def newfunc(a,b):
print a
or
def newfunc(**kwargs):
print kwargs["a"]
Taking a look at your code, you seem to struggle with the concepts of how to deal with dictionaries. Maybe the question you're asking would be easier for you to answer yourself if your sat back and read a tutorial on python's dict
Two things.
First, your kwargs argument in myfunc is an empty dict, so you won't pass any parameters. If you want to pass the value of a and b to newfunc, you can either use
kwargs = {'a':1, 'b':2}
newfunc(**kwargs)
or
newfunc(a=1, b=2)
In both cases, you will get 'a' and 'b' in the kwargs dict of the newfunc function.
Second, you should extract your argument from the kwargs dict in newfunc. Something like print kwargs.get('a') should suffice.

Alias for dictionary operation in Python

I want to do something like this:
f[frozenset((1,3,4))] = 5
f[frozenset((1,))] = 3
but it's just painful to type these all the time, is there anyway to have alias for this? I know in C++ it's possible to have a helper function which return a reference so you can just type:
F(1,3,4) = 5
F(1) = 3
with F as a helper function. Thanks very much!
I think that this can really only be achieved via a subclass:
class FrozenSetDict(dict):
def __setitem__(self,idx,value):
try:
dict.__setitem__(self,frozenset(idx),value)
except TypeError:
dict.__setitem__(self,frozenset((idx,)),value)
d = FrozenSetDict()
d[1,2,3] = 4
d[1] = 5
print d
yields:
{frozenset([1, 2, 3]): 4, frozenset([1]): 5}
This introduces an asymmetry between __getitem__ and __setitem__ which could easily be fixed by re-defining __getitem__ in the same way.
This might seem a little messy -- Indeed it is. Why require a subclass? That just makes it harder to put non-frozenset objects into your dictionary as keys. You could easily use this recipe though to create a proxy object which will do this with your dict:
#I don't like the name of this class -- I'm open to suggestions :)
class FrozenSetProxy(object):
def __init__(self,obj):
self.obj = obj
def __setitem__(self,idx,value):
try:
self.obj[frozenset(idx)] = value
except TypeError:
self.obj[frozenset((idx,))] = value
def __getitem__(self,idx):
try:
return self.obj[frozenset(idx)]
except TypeError:
return self.obj[frozenset((idx,))]
d = dict()
F = FrozenSetProxy(d)
F[1,2,3] = 4
F[1] = 5
print d
print F[1]
There's nothing like a C++ reference in Python, and the syntax you use is illegal to boot (in the words of the parser: can't assign to function call). You could emulate it with an object or subclass dict to customize its __getitem__. But there's a simpler and less intrusive way: Pass the value to the helper too, and let it handle the assignment:
def blah(f):
def F(*args, value):
f[frozenset(args)] = value
F(1, 3, 4, value=5)
F(1, value=3)
Note that this uses a Python 3 feature, keyword-only parameters. If you need it to work with Python 2, you can emulate the call syntax by accepting **kwdargs:
def F(*args, **kwds):
# optional: check that no other keyword arguments were passed
f[frozenset(args)] = kwds['value']

How to bind arguments to given values in Python functions? [duplicate]

This question already has answers here:
Python Argument Binders
(7 answers)
Closed 4 years ago.
I have a number of functions with a combination of positional and keyword arguments, and I would like to bind one of their arguments to a given value (which is known only after the function definition). Is there a general way of doing that?
My first attempt was:
def f(a,b,c): print a,b,c
def _bind(f, a): return lambda b,c: f(a,b,c)
bound_f = bind(f, 1)
However, for this I need to know the exact args passed to f, and cannot use a single function to bind all the functions I'm interested in (since they have different argument lists).
>>> from functools import partial
>>> def f(a, b, c):
... print a, b, c
...
>>> bound_f = partial(f, 1)
>>> bound_f(2, 3)
1 2 3
You probably want the partial function from functools.
As suggested by MattH's answer, functools.partial is the way to go.
However, your question can be read as "how can I implement partial". What your code is missing is the use of *args, **kwargs- 2 such uses, actually:
def partial(f, *args, **kwargs):
def wrapped(*args2, **kwargs2):
return f(*args, *args2, **kwargs, **kwargs2)
return wrapped
You can use partial and update_wrapper to bind arguments to given values and preserve __name__ and __doc__ of the original function:
from functools import partial, update_wrapper
def f(a, b, c):
print(a, b, c)
bound_f = update_wrapper(partial(f, 1000), f)
# This will print 'f'
print(bound_f.__name__)
# This will print 1000, 4, 5
bound_f(4, 5)

Python - Passing a function into another function [duplicate]

This question already has answers here:
Python function as a function argument?
(10 answers)
Closed last month.
I am solving a puzzle using python and depending on which puzzle I am solving I will have to use a special set of rules. How can I pass a function into another function in Python?
Example
def Game(listA, listB, rules):
if rules == True:
do...
else:
do...
def Rule1(v):
if "variable_name1" in v:
return False
elif "variable_name2" in v:
return False
else:
return True
def Rule2(v):
if "variable_name3" and "variable_name4" in v:
return False
elif "variable_name4" and variable_name1 in v:
return False
else:
return True
This is just a pseudo code and therefore not specific but I get the code to compile but I need to know how to call the function Game and whether it's correctly defined since rules will be switched for either Rule1(v) or Rule2(v).
Just pass it in like any other parameter:
def a(x):
return "a(%s)" % (x,)
def b(f,x):
return f(x)
print b(a,10)
Treat function as variable in your program so you can just pass them to other functions easily:
def test ():
print "test was invoked"
def invoker(func):
func()
invoker(test) # prints test was invoked
For passing both a function, and any arguments to the function:
from typing import Callable
def looper(fn: Callable, n:int, *args, **kwargs):
"""
Call a function `n` times
Parameters
----------
fn: Callable
Function to be called.
n: int
Number of times to call `func`.
*args
Positional arguments to be passed to `func`.
**kwargs
Keyword arguments to be passed to `func`.
Example
-------
>>> def foo(a:Union[float, int], b:Union[float, int]):
... '''The function to pass'''
... print(a+b)
>>> looper(foo, 3, 2, b=4)
6
6
6
"""
for i in range(n):
fn(*args, **kwargs)
Depending on what you are doing, it could make sense to define a decorator, or perhaps use functools.partial.
Just pass it in, like this:
Game(list_a, list_b, Rule1)
and then your Game function could look something like this (still pseudocode):
def Game(listA, listB, rules=None):
if rules:
# do something useful
# ...
result = rules(variable) # this is how you can call your rule
else:
# do something useful without rules
A function name can become a variable name (and thus be passed as an argument) by dropping the parentheses. A variable name can become a function name by adding the parentheses.
In your example, equate the variable rules to one of your functions, leaving off the parentheses and the mention of the argument. Then in your game() function, invoke rules( v ) with the parentheses and the v parameter.
if puzzle == type1:
rules = Rule1
else:
rules = Rule2
def Game(listA, listB, rules):
if rules( v ) == True:
do...
else:
do...

Categories

Resources