This is a little bit weird. I want to dynamic initialize part of function's parameters before I call it. But I don't want to use class for some reason. Let's say I have a function:
def inner(a,b,c):
"a,b,c do something"
return result
Before I formally call it, I'd like to initialize it somewhere:
partInitalAbc=inner(,b,c)
Then I'll use it as:
result=partInitialAbc(a)
Please notice I want to do this dynamically. Just as when you initial a class using the constructor, so a decorator may be not appropriate at this time...
Any one have some idea?
It sounds like you're looking for functools.partial:
Return a new partial object which when called will behave like func called with the positional arguments args and keyword arguments keywords.
If you pass the arguments to partial as positional arguments, they'll appear at the beginning of the argument list, which isn't exactly what you want. Keyword arguments give you more control over which parameters are passed:
partInitialAbc = functools.partial(inner, b=b_value, c=c_value);
Related
I have two functions defined roughly like this:
def func_inner(bar=0):
print('inner bar:', bar)
def func_outer(bar=-1, *args, **kwargs):
print('outer bar:', bar)
func_inner(*args, **kwargs)
Is there a way to call func_outer and provide it with two values of bar - one for func_outer, and the other to be passed over to func_inner? Calling func_outer(bar=1,bar=2) clearly does not work.
It's possible to overcome the issue by specifying bar values as positional arguments, like func_outer(1,2), but I'd like to specify them as keyword arguments for both functions.
Is there a solution entirely at the caller's side (ie. without altering the functions)?
No, there is none
You cannot pass two arguments with the same name to a function. Thus, you will not be able to have the key "bar" in kwargs.
Thus you cannot pass this argument without modifying the two functions.
There may be a more adapted way to what you’re doing
This is the kind of code that pops up in a decorator. In this kind of case, you may want to make the outer function currified.
When doing a method call in Python, in which cases do you use the = sign when entering arguments?
I noticed sometimes it's:
object.method(argument1 = ... , argument2 = ...)
and other times it's
object.method(... , ...)
Thanks in advance!
That types of arguments are called keyword arguments, probably you've seen that as (kwargs).
In a function you can pass 2 types of args, positional arguments and keyword-arguments.
def function(arg):
So you have to pass inside this function a positional argument, this means that you have to pass only the value for that arg like
function(1) or maybe a string function("hello") or maybe a list and so on; This type of arg is called position arg.
When you have to specify the name of the variable inside the brackets of a function call like function(name = "John"), you are using the keyword args.
If you want to understand more on this topic, i suggest you to see the unpack operator in Python (*) and then *args and **kwargs.
2 words to say what *args and **kwargs do in Python, they allows you to specify an unlimited number of arguments inside a function call.
def function(*args, **kwargs):
pass
function(1,2,3,"hello",[1,2,3],name="John",age=5)
In python, it is possible to check whether a function makes function calls where named arguments are called as positional arguments?
For example:
def a(pos_arg, nam_arg=None, nam_arg2=None):
return "whatever"
def b():
return a(1, 2, nam_arg2="whatever")
Here, the function b calls the function a, but the second argument is a named argument, which is being called as a positional argument. This might cause confusing problems when object inheritance comes into play.
Better would have been:
def b():
return a(1, nam_arg=2, nam_arg2="whatever")
For testing purposes (as this is generally bad code in my project), I would like to find out whether the function b() makes such calls.
Is this possible in python?
You tagged your question as python-2.7 but for the sake of future viewers I would say that in python 3 we now have keyword-only arguments feature which allows to define a function like that:
def func(pos_arg, *, kw_only_arg):
pass
In that case kw_only_arg is allowed to be used only as keyword argument.
If you can't use python 3 then there is a recipe that can help you with that:
http://code.activestate.com/recipes/578993-keyword-only-arguments-in-python-2x/
Some decorators should only be used in the outermost layer.
A decorator that augments the original function and add a configure parameter is one example.
from functools import wraps
def special_case(f):
#wraps(f)
def _(a, b, config_x=False):
if config_x:
print "Special case here"
return
return f(a, b)
How can I avoid decorators like this getting decorated by another decorator?
EDIT
It is really disgusting to let everyone trying to apply a new decorator worry about the application order.
So, is it possible to avoid this kind of situation? Is it possible to add a config option without introducing a new parameter?
There isn't any way to stop it from being decorated. You just have to document that it needs to apply last and tell people not to use it inside another decorator.
Edit responding to your edit: In Python 3 you can give your function a keyword-only argument. This drastically reduces the impact that the change will have on existing uses of the function. Unfortunately this only works in Python 3.
Ultimately, applying a decorator to a function just means passing the decorated function as an argument to another function. There's no way for a function (or any object) to even know that it's being passed as an argument, let alone what it's being passed to. The reason you can't know about later decorators is the same reason that in an ordinary function call like f(g(x)), the function g can't know that it will later be called by f.
This is one reason writing decorators is tricky. Code that relies on heavy use of decorators that pass explicit arguments to their wrapped functions (as yours passes a and b) is inherently going to be fragile. Fortunately, a lot of the time you can write a decorator that uses *args and **kwargs so it can pass all the arguments it doesn't use along to the decorated function.
If someone takes the code you provide, and writes another decorator that explicitly accepts only a and b as arguments, and then calls the decorated function as f(a, b, True), it's their own fault if it fails. They should have known that other decorators they used might have changed the function signature.
Normally, when one write a decorator to be used generically, one does not estrict the number or name of arguments for the function it is wrapping.
Most decorators out there accept a list o positional arguments, and amapping of keyword arguments as parameters for their wrapper, and pass those, as received, to the decorated function:
def deco(func):
def wrapper(*args, **kwargs):
... decorator stuff here ...
return func(*args, **kwargs)
Threfore, if the decorator is to receive a parameter that it should "consume" - like the config_x you mention, all you have to do is to document it, have it as a keyword parameter, and pick it from kwargs. To avoid name clashes on parameters, one can, for example, prefix this parameter name with the decorator's own name or other distinct name:
def deco(func):
def wrapper(*args, **kwargs):
if "deco_config_x" in kwargs):
config_x = kwargs.pop(deco_config_x)
... decorator stuff here ...
return func(*args, **kwargs)
This way, the decorator may be put anywhere on a "decorator stack" - it will pick the parameter(s) addressed to it, and those bellow it won't get any stranger parameter. Theonly requirement is that your functions and decorators as a whole juts let keyword parametrs they don't know about to pass through.
So I am trying out the new python code for the google app engine search library and I came across a weird syntax. This was:
cls_createDocument(**params)
where params was a dictionary.
The function this refers to is:
#classmethod
def _createDocument(
cls, pid=None, category=None, name=None, description=None,
category_name=None, price=None, **params)
My questions is, what does the **params signify and what does that do to the object?
Thanks!
Jon
Consider a function with default arguments:
def func(foo=3):
print(foo)
The structure of the arguments is (in principle) very similar to a dictionary. The function foo has (essentially) a dictionary of default arguments (in this case {'foo':3}). Now, lets say that you don't want to use the keyword in the function call, but you want to use a dictionary instead -- then you can call foo as:
d = {"foo":8}
func(**d)
This allows you to dynamically change what arguments you are passing to the function func.
This become a little more interesting if you try the following:
d = {"foo":8, "bar":12}
func(**d)
This doesn't work (it is equivalent to foo(foo=8, bar=12), but since bar isn't a valid argument, it fails).
You can get around that problem by giving those extra arguments a place to go inside the definition of foo.
def func( foo=3, **kwargs ):
print(foo,kwargs)
Now, try:
d = {"foo":8, "bar":12}
func(**d) #prints (8, {'bar':12})
All the extra keyword arguments go into the kwargs dictionary inside the function.
This can also be called as:
func(foo=8, bar=12)
with the same result.
This is often useful if funcA calls funcB and you want funcA to accept all of the keywords of funcB (plus a few extra) which is a very common thing when dealing with classes and inheritance:
def funcA(newkey=None,**kwargs):
funcB(**kwargs)
Finally, here is a link to the documentation
The **params parameter represents all the keyword arguments passed to the function as a dictionary.