unable to understand lambda map function - python

Seeking guidance to understand a lambda-map function. In the below, I see that the file "feedback" is read line by line and stored in a list "feedback". I'm unable to get my head around the variable x. I don't see the variable "x" declared anywhere. Can someone help me understand the statement?Thanks in advance
f = open('feedback.txt','r')
feedback = list(map(lambda x:x[:-1],f.readlines())
f.close()

The map function will execute the given function for every element in the list.
In your code the map function will get lambda x:x[:-1].
You can read that like: for every x in f.readlines() return everything except the last element of x.
So x will be every line the file. lambda x: you could see as def thing(x):.

I replaced lambda with a standard func:
def read_last(x): #x means a line
return x[:-1]
f = open('feedback.txt','r')
feedback = list(map(read_last, f.readlines())
f.close()
Maybe it will help.

lambda function is a simple anonymous function that takes any number of arguments, but has only one expression.
lambda arguments : expression
It is anonymous because we have not assigned it to an object, and thus it has no name.
example f and g are somewhat same:
def f(x):
# take a string and return all but last value
return x[:-1]
g = lambda x: x[:-1]
so:
f('hello') == g('hello') #True ->'hell'
But g is not how we would use lambda. The whole aim is to avoid assigning ;)
Now map takes in a function and applies it to an iteratable:it returns a generator in Python 3+ and thus a list is used to case that generator to a list
data = ['we are 101','you are 102','they are 103']
print(list(map(lambda x:x[:-1],data)))
#->['we are 10','you are 10','they are 10']
In principle, same as passing a function:
data = ['we are 101','you are 102','they are 103']
print(list(map(f,data)))
but often faster and awesome. I love lambdas

Keep in mind, while explaining lambda is solved here, it is not the implementation of choice for your particular example. Suggestion:
f = open('feedback.txt', 'r')
feedback = f.read().splitlines()
f.close()
See also 'Reading a file without newlines'.

Related

How can I get the function object inside a lambda function

Sorry if this is very lame, but I'm pretty new to Python.
As in Python everything is an object, I assume in every object the object itself can be get somehow. In object methods the self variable contains it. From the object reference the class object can be get (like type(self)). But how this could be got inside a lambda?
I could figure out for a normal function:
import inspect
def named_func():
func_name = inspect.stack()[0].function
func_obj = inspect.stack()[1].frame.f_locals[func_name]
print(func_name, func_obj, func_obj.xxx)
named_func.xxx = 15
named_func()
The output looks like this:
named_func <function named_func at 0x7f56e368c2f0> 15
Unfortunately in a lambda the inspect.stack()[0].function gives <lambda> inside the lambda.
Is there a way to get the function object inside a lambda?
Is there a way to get function object directly (not using the name of the function)?
I imagined __self__, but it does not work.
UPDATE
I tried something like this in lambda:
lambda_func = lambda : inspect.stack()[0]
lambda_func.xxx = 2
print(lambda_func())
This prints:
FrameInfo(frame=<frame at 0x7f3eee8a6378, file './test_obj.py', line 74, code <lambda>>, filename='./test_obj.py', lineno=74, function='<lambda>', code_context=['lambda_func = lambda : inspect.stack()[0]\n'], index=0)
But for example is there a way to get the lambda object field xxx in this case? For this the lambda object should be got somehow.
We can now use a new python syntax to make it shorter and easier to read, without the need to define a new function for this purpose.
You can find two examples below:
Fibonacci:
(f:=lambda x: 1 if x <= 1 else f(x - 1) + f(x - 2))(5)
Factorial:
(f:=lambda x: 1 if x == 0 else x*f(x - 1))(5)
We use := to name the lambda: use the name directly in the lambda itself and call it right away as an anonymous function.
So in your particular use-case it would give something like that:
print((f:=lambda: f.__hash__())()) # prints the hash for example
You can do whatever you want with that f variable now (inside the lambda).
But in fact, if you don't mind multi-lines for your code, you could also just use the name directly and do something like that:
f = lambda : f.xxx
f.xxx = 2
print(f())
(see https://www.python.org/dev/peps/pep-0572 for more information about this := operator)
Note, this is not an efficient/pragmatic solution to the problem. This is not a recommendation about how to write actual software.. it simply presents how access to the lambda reference from the lambda can be achieved without assigning it to a variable name. This is a very hacky answer.
This will only work completely correctly if you follow the advice from the answer found here
In short, given the stack you can find the code object, and then using the gc module you can find the reference to your lambda.
Example with #Tomalak's factorial lambda!
import gc
import inspect
def current_lambda():
lambda_code = inspect.stack()[1].frame.f_code
candidates = [
referrer
for referrer in gc.get_referrers(lambda_code)
if inspect.isfunction(referrer)
and referrer.__code__ is lambda_code
]
if len(candidates) != 1:
raise ValueError(
"Multiple candidates found! Cannot determine correct function!"
)
return candidates[0]
print((lambda n: 1 if n < 2 else n * current_lambda()(n - 1))(5))
Outputs
120
Revisiting your example:
lambda_func = lambda: current_lambda().xxx
lambda_func.xxx = 10
print(lambda_func())
Outputs:
10

Python - notation for redundant lambda parameters

I am trying to build a function
f(x, y, z)
where neither x nor y have any impact on the result. Nonetheless, they must be passed to the function, as the passing is done by a library. I would like to:
solve this using a lambda expression, and
ensure that anyone reading my code will immediately know that x and y are redundant.
As I have gathered, using the underscore character for redundant return values from multiple-value-returning functions is common practice, e.g.
a, _, c, d, _, _ = return_six_things(),
however, trying
f = lambda _, _, z: some_operation(z)
crashes with the exception warning the author about using 'duplicate arguments' (two underscore characters).
Are there any other options?
P.S. to avoid the XY problem, the reason I want to use lambdas is to save a few source code characters. I would love to use them anyway, but declaring that "these parameters will not be used" is more important for me.
I'd use a double underscore (__) for the second unused argument:
f = lambda _, __, z: some_operation(z)
Options:
# pass in z as a keyward argument
# like this: f(x,y,z=1)
f = lambda *_,z: some_operation(z)
#Or:
# pass in any number of arguments and only use the last argument
f = lambda *z: some_operation(z[-1])

python, basic lambda function

I am a c++ guy, learning the lambda function in python and wanna know it inside out. did some seraches before posting here. anyway, this piece of code came up to me.
<1> i dont quite understand the purpose of lambda function here. r we trying to get a function template? If so, why dont we just set up 2 parameters in the function input?
<2> also, make_incrementor(42), at this moment is equivalent to return x+42, and x is the 0,1 in f(0) and f(1)?
<3> for f(0), does it not have the same effect as >>>f = make_incrementor(42)? for f(0), what are the values for x and n respectively?
any commments are welcome! thanks.
>>> def make_incrementor(n):
... return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43
Yes, this is similar to a C++ int template. However, instead of at compile time (yes, Python (at least for CPython) is "compiled"), the function is created at run time. Why the lambda is used in this specific case is unclear, probably only for demonstration that functions can be returned from other functions rather than practical use. Sometimes, however, statements like this may be necessary if you need a function taking a specified number of arguments (e.g. for map, the function must take the same number of arguments as the number of iterables given to map) but the behaviour of the function should depend on other arguments.
make_incrementor returns a function that adds n (here, 42) to any x passed to that function. In your case the x values you tried are 0 and `1``
f = make_incrementor(42) sets f to a function that returns x + 42. f(0), however, returns 0 + 42, which is 42 - the returned types and values are both different, so the different expressions don't have the same effect.
The purpose is to show a toy lambda return. It lets you create a function with data baked in. I have used this less trivial example of a similar use.
def startsWithFunc(testString):
return lambda x: x.find(testString) == 0
Then when I am parsing, I create some functions:
startsDesctription = startsWithFunc("!Sample_description")
startMatrix = startsWithFunc("!series_matrix_table_begin")
Then in code I use:
while line:
#.... other stuff
if startsDesctription(line):
#do description work
if startMatrix(line):
#do matrix start work
#other stuff ... increment line ... etc
Still perhaps trival, but it shows creating general funcitons with data baked it.

Python - Use a print/debug statement within a Lambda

I have a filter in Python3 that I am applying with a lambda function. Here is my function:
affy_reader = csv.DictReader(filter(lambda row:
not row[0].startswith('#') and
str(row[0]).isdigit(),
file_pointer),
delimiter='\t',
fieldnames=affy_column_headers)
Is there a way that I can print the value of row from within this lambda function? I think I need to do it like this because row is only scoped within the lambda. For example, were this a LISP Lambda procedure, I believe I could do something like this:
affy_reader = csv.DictReader(filter(lambda row: print(row)
not row[0].startswith('#') and
str(row[0]).isdigit(),
file_pointer),
delimiter='\t',
fieldnames=affy_column_headers)
Because the print() is read and executed in-line. Is there some way in Python to do this? Or if not, what is a good way for me to see this value? Thanks!
*I realize my "LISP" example is Python not LISP. I was just trying to illustrate further what it is I am trying to do.
I don't think you can do it with a lambda. Just define a helper function. That way you can also display whether a certain row is or isn't going to be filtered:
def filter_plus_print(row):
result = not row[0].startswith('#') and str(row[0]).isdigit()
print("Keeping:" if result else "Removing:", row)
return result
and then do
affy_reader = csv.DictReader(filter(filter_plus_print, file_pointer),
delimiter='\t',
fieldnames=affy_column_headers)
General Python 3.x trick to print debug info in a lambda without changing its semantics:
Original:
lambda: 4
Instrumented:
lambda: (print (3), 4) [1]
Explanation:
Both arguments of the tuple will be evaluated.
The left one, print (3) in the example, is relying purely on a sideeffect, i.e. in this case it will print something. You can call any function here, since any Python function will return a value. This value will be the Python predefined value None if a return statement is missing. This doesn't matter since the return value isn't used anywhere.
The second argument, 4 in the example, can be any expression including a function call or a call to a functor (object with overloaded round brackets). This argument is returned by the lambda function by selecting [1], i.e. the second element of the tuple (indexing in Python starts at 0].
The reason why this works specifically in Python 3.x is that print is a "perfectly ordinary" function there, whereas in Python 2.x it was a statement.
You can view the values within file_pointer by printing it directly.
print(file_pointer)
affy_reader = csv.DictReader(filter(lambda row:
not row[0].startswith('#') and
str(row[0]).isdigit(),
file_pointer),
delimiter='\t',
fieldnames=affy_column_headers)
There is no pythonic way to execute multiple statements in an anonymous function. I would suggest breaking the lambda out to a named function, like so:
def relevant(row):
print(row)
return not row[0].startswith('#') and str(row[0]).isdigit()
affy_reader = csv.DictReader(filter(relevant, file_pointer),
delimiter='\t',
fieldnames=affy_column_headers)
The problems is that print(row) returns None and you have to do something with it. Rather unpleasant in most cases.

How can I automatically run all the functions in the module?

I need to run several functions in a module as follws:
mylist = open('filing2.txt').read()
noTables = remove_tables(mylist)
newPassage = clean_text_passage(noTables)
replacement = replace(newPassage)
ncount = count_words(replacement)
riskcount = risk_count(ncount)
Is there any way that I can run all the functions at once? Should I make all the functions into a big function and run that big function?
Thanks.
You should make a new function in the module which executes the common sequence being used. This will require you to figure out what input arguments are required and what results to return. So given the code you posted, the new function might look something like this -- I just guessed as to what final results you might be interested in. Also note that I opened the file within a with statement to ensure that it gets closed after reading it.
def do_combination(file_name):
with open(file_name) as input:
mylist = input.read()
noTables = remove_tables(mylist)
newPassage = clean_text_passage(noTables)
replacement = replace(newPassage)
ncount = count_words(replacement)
riskcount = risk_count(ncount)
return replacement, riskcount
Example of usage:
replacement, riskcount = do_combination('filing2.txt')
If you simply store these lines in a Python (.py) file you can simply execute them.
Or am I missing something here?
Creating a function is also easy to call them though:
def main():
mylist = open('filing2.txt').read()
noTables = remove_tables(mylist)
newPassage = clean_text_passage(noTables)
replacement = replace(newPassage)
ncount = count_words(replacement)
riskcount = risk_count(ncount)
main()
As far as I understood, use need function composition. There is no special function for this in Python stdlib, but you can do this with reduce function:
funcs = [remove_tables, clean_text_passage, replace, count_words, risk_count]
do_all = lambda args: reduce(lambda prev, f: f(prev), funcs, args)
Using as
with open('filing2.txt') as f:
riskcount = do_all(f.read())
Here's another approach.
You could write a general function somewhat like that shown in the First-class composition section of the Wikipedia article on Function composition. Note that unlike in the article the functions are applied in the the order they are listed in the call to compose().
try:
from functools import reduce # Python 3 compatibility
except:
pass
def compose(*funcs, **kwargs):
"""Compose a series of functions (...(f3(f2(f1(*args, **kwargs))))) into
a single composite function which passes the result of each
function as the argument to the next, from the first to last
given.
"""
return reduce(lambda f, g:
lambda *args, **kwargs: f(g(*args, **kwargs)),
reversed(funcs))
Here's a trivial example illustrating what it does:
f = lambda x: 'f({!r})'.format(x)
g = lambda x: 'g({})'.format(x)
h = lambda x: 'h({})'.format(x)
my_composition = compose(f, g, h)
print my_composition('X')
Output:
h(g(f('X')))
Here's how it could be applied to the series of functions in your module:
my_composition = compose(remove_tables, clean_text_passage, replace,
count_words, risk_count)
with open('filing2.txt') as input:
riskcount = my_composition(input.read())

Categories

Resources