In Python, for a simple function foo(x, y) there are at least 3 ways that i know to bind the argument y to some value
# defining a nested function:
def foobar(x):
return foo(x, y=yval)
# using lambda
foobar = lambda x: foo(x, y=yval)
# using functools
from functools import partial
foobar = partial(foo, y=yval)
while i am doubtful that the list above is exhaustive, i also wonder which one should i go with? are they all equivalent in terms of performance, safety and namespace handling? or are there extra overheads and caveats with each method? why should functools define partial when the other methods are already there?
No, they're not all equivalent -- in particular, a lambda cannot be pickled and a functools.partial can, IIRC, be pickled only in recent Python versions (I can't find which exact version in the docs; it doesn't work in 2.6, but it does in 3.1). Neither can functions defined inside of other functions (neither in 2.6 nor 3.1).
The reason for partial's appearance in the library is that it gives you an explicit idiom to partially apply a function inline. A definition (def) cannot appear in the middle of an expression such as
map(partial(foo, y=yval), xs)
Also, from a definition or lambda, it's not immediately clear that partial application is what's going on, since you can put an arbitrary expression in a lambda and arbitrary statements in a definition.
I suggest you go with partial unless you have a reason not to use it.
[And indeed, the list is not exhaustive. The first alternative that comes to mind is a callable object:
class foobar:
def __init__(self, yval):
self.__yval = yval
def __call__(self, x):
return foo(x, self.__yval)
but those are heavy-weights for such a simple problem.]
Related
I have come across some code that uses lambda expressions on multiple occasions to pass around classes.
class Clazz:
def __init__(self, a, b=-1):
self.a = a
self.b = b
def __str__(self):
return f'Clazz: {self.a}; {self.b}'
clazz_fn1 = lambda a: Clazz(a) # o1_fn is than passed to some other function ...
c1 = clazz_fn1(1) # ... where the Clazz object is initialized
print(c1)
Is there any advantage in using a the lambda keyword over just passing the class name?
clazz_fn2 = Clazz
c2 = clazz_fn2(2)
print(c2)
The only advantage that comes to my mind, is that lambda functions offer the possibility to pass further arguments along:
clazz_fn3 = lambda a: Clazz(a, b=42)
c3 = clazz_fn3(3)
print(c3)
On the other hand, it is my understanding that using lambda functions is not something that is generally recommended (see e.g. this posts: Guido van Rossum interview, post on overusing of lambda expressions... still this discussion seems to be mostly in favour of lambda expressions).
I am also aware of the question on why to use lambda functions, but using lambda functions to pass around classes as described above does not seem to be the typical use case for the lambda syntax that is covered by this more general discussion.
So are there further differences between the two options or is this a purely stylistic choice?
Is there any advantage in using a the lambda keyword over just passing the class name?
Not really. In the simple case you show, you are just adding a (IMHO unneeded) level of indirection to the instantiation process. Using the class name itself would be simpler and more comprehensible.
The only advantage that comes to my mind, is that lambda functions offer the possibility to pass further arguments along:
Yeah, that's a good use case. In fact, it's such a common use case that functools.partial() was invented exactly for this purpose:
from functools import partial
clazz_fn3 = partial(Clazz, b=42)
c3 = clazz_fn3(3)
print(c3)
So are there further differences between the two options or is this a purely stylistic choice?
I'd say this is most definitely a stylistic choice of the programmer. Other than the obvious difference in the slightly more (unneeded) overhead when wrapping using a lambda, there isn't much else of objective relevance that'd make one of the two versions preferable over the other.
I've got some code I'm porting to Cython which had a line like
my_list.sort(key=lambda x: x.attr[item])
Is there a nice pythonic way of avoiding the closure with some combination of itemgetter and attrgetter?
The key is to use the package functional:
from functional import compose
from operator import attrgetter, itemgetter
my_list.sort(key=compose(itemgetter(item), attrgetter('attr')))
The accepted self answer feels like a mistake/de-optimization to me.
My guess is that the unstated problem is that closures aren't supported inside cpdef functions. However closures are supported inside both cdef and def functions.
My view is that there's rarely a reason to use cpdef functions - they have all the disadvantages of def functions and all the disadvantages of cdef functions (plus a few more unique disadvantages, like no closures) so I usually treat them as the worst of all worlds. Ideally you'd just decide if something should be a Cython/C interface (cdef) or a Python interface def and use that. Also remember that the type of function makes little to no difference to how the code inside it is compiled, so a find/replace of def for cpdef really is redundant when porting to Cython.
Therefore for this case I would keep the closure as written in the original Python code and pick one of:
Just keep it as a def function.
If you really need to call it from both Python and need the speed of a cdef call when calling it from Cython then write a cdef function and a really small def function wrapper for the cdef function.
The code in the accepted answer is de-optimizing an attribute lookup and an index into at least(?) 3 Python function calls, an attribute lookup, and an index.
I know python does not allow us to overload functions. However, does it have inbuilt overloaded methods?
Consider this:
setattr(object_name,'variable', 'value')
setattr(class_name,'method','function')
The first statement dynamically adds variables to objects during run time, but the second one attaches outside functions to classes at run time.
The same function does different things based on its arguments. Is this function overload?
The function setattr(foo, 'bar', baz) is always the same as foo.bar = baz, regardless of the type of foo. There is no overloading here.
In Python 3, limited overloading is possible with functools.singledispatch, but setattr is not implemented with that.
A far more interesting example, in my opinion, is type(). type() does two entirely different things depending on how you call it:
If called with a single argument, it returns the type of that argument.
If called with three arguments (of the correct types), it dynamically creates a new class.
Nevertheless, type() is not overloaded. Why not? Because it is implemented as one function that counts how many arguments it got and then decides what to do. In pure Python, this is done with the variadic *args syntax, but type() is implemented in C, so it looks rather different. It's doing the same thing, though.
Python, in some sense, doesn't need a function overloading capability when other languages do. Consider the following example in C:
int add(int x, int y) {
return x + y;
}
If you wish to extend the notion to include stuff that are not integers you would need to make another function:
float add(float x, float y) {
return x + y;
}
In Python, all you need is:
def add(x, y):
return x + y
It works fine for both, and it isn't considered function overloading. You can also handle different cases of variable types using methods like isinstance. The major issue, as pointed out by this question, is the number of types. But in your case you pass the same number of types, and even so, there are ways around this without function overloading.
overloading methods is tricky in python. However, there could be usage of passing the dict, list or primitive variables.
I have tried something for my use cases, this could help here to understand people to overload the methods.
Let's take the example:
a class overload method with call the methods from different class.
def add_bullet(sprite=None, start=None, headto=None, spead=None, acceleration=None):
pass the arguments from remote class:
add_bullet(sprite = 'test', start=Yes,headto={'lat':10.6666,'long':10.6666},accelaration=10.6}
OR add_bullet(sprite = 'test', start=Yes,headto={'lat':10.6666,'long':10.6666},speed=['10','20,'30']}
So, handling is being achieved for list, Dictionary or primitive variables from method overloading.
try it out for your codes
operator provides attrgetter to make a function that retrieves a field from an object.
Why isn't this included in operator (or somewhere else in the standard libraries)?
def attrsetter(name):
def setter( obj, val):
setattr(obj, name, val)
return setter
The only reason that I can think of is that there are edge cases where this straightforward approach will break. In which case, what are these edge cases so that I can try to trap/avoid them?
attrgetter is designed to be used in places where a function is required as a replacement for lambda. For example:
# equivalent
heads = map(attrgetter('head'), objs)
heads = map(lambda o: o.head, objs)
In other words, the point of attrgetter is to create a side-effect-free function that returns a useful value, and which can be used in expressions that require a function. An attrsetter, on the other hand, would only operate by side effect, and would need to return None by Python convention. Since attrsetter would not be at all useful as argument to map and similar, it is not provided. If you need attrsetter, simply write a normal for loop.
Also note that both of the above idioms are better expressed with a list comprehension:
heads = [o.head for o in objs]
attrgetter is rarely needed and has lost much of its appeal once it was decided that lambda would not be removed from Python 3 after all.
In some code I'm writing, I'd like a function similar to the built in sum() function, except with my own custom two-argument function as opposed to addition. It's easy to write such a function, but I'm wondering if there's one in the standard library somewhere? I took a look through the itertools doc, but didn't find anything. It would also be similar to itertools.accumulate(mylist)[-1], except with functions other than sums.
My own code for such a function:
def accumulate(iterable, func):
it = iter(iterable)
out = func(next(it), next(it))
for i in it:
out = func(out, i) # "out += i"
return out
So sum(mylist) would be equivalent to accumulate(mylist, lambda x, y: x+y). In my use case of course, I have a different function I'd like to use (it is more complicated than a simple arithmetic operation.)
It seems like this would be a fairly common thing, which is why I'm surprised half an hour of searching didn't find anything like this. So: If and where does such a function exist in the standard library? (I'm using my own code above for now.)
The usual name for that function is fold or reduce, and it's actually built into Python 2 under the latter name:
>>> reduce(lambda x,y: x*y, [1,3,5,4])
60
In Python 3 you have to import it from the functools module.