'lambda expresion that return the names of the function from a list that have more then one parameter
I need to make a lambda expresion that return the names of the function from a list that have more then one parameter, I wrote the code below but insted of giving me the name of the function it return this <function funB at 0x01FDBE80>. How can I fix it?
def funA():
pass
def funB(a):
pass
def funC(a, b):
pass
n = [funA, funB, funC]
m = list(filter(lambda x: x.__name__ if x.__code__.co_argcount > 0 else None, n))
print(m)
Solution 1:[1]
To avoid such side effects just add a further step (see explanation of DeepSpace), filter and the retrieve the name with map
(as required).
fs = [funA, funB, funC]
fs_filtered = map(lambda f: f.__name__, filter(lambda f: f if f.__code__.co_argcount > 0 else None , fs))
print(list(fs_filtered))
or better:
fs_filtered = filter(None, map(lambda f: f.__name__ if f.__code__.co_argcount > 0 else None, fs))
print(list(fs_filtered ))
Appendum: filter
is made just for filter, no action of the items of the iterator is supported. In this example the print
works perfectly but again the .__name__
is ignored at the end
m = list(filter(lambda f: (print(f.__name__), f.__name__)[1] if f.__code__.co_argcount > 0 else None, fs))
# funB
# funC
# [<function funB at 0x7f6337eeddc0>, <function funC at 0x7f6337eede50>]
Solution 2:[2]
The issue is that filter
uses the function it is given as a boolean predicate purely for filtering and not for changing the yielded value.
In this example, it will add to the resulting generator all the functions for which x.__name__ if x.__code__.co_argcount > 0 else None
is True
, but it will add the function object itself as is, not its .__name__
attribute.
From the docs:
Construct an iterator from those elements of iterable for which function returns true. iterable may be either a sequence, a container which supports iteration, or an iterator. If function is None, the identity function is assumed, that is, all elements of iterable that are false are removed. Note that filter(function, iterable) is equivalent to the generator expression (item for item in iterable if function(item)) if function is not None and (item for item in iterable if item) if function is None.
That is why
m = list(filter(lambda x: x.__code__.co_argcount > 0, n))
will give the same output as the code you currently have.
In this case you should not use filter
:
m = list(f.__name__ for f in n if f.__code__.co_argcount > 0)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |