Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
When I'm reading docs or examples, I often see the idea come up that you can assign an anonymous function to a variable. Why would I ever actually do this rather than just define a new function?
Some examples:
Clojure/Lisp
(def add2
(fn [a] (+ 2 a))
(add2 4) ;; => 6
Python
add2 = lambda e: e + 2
add2(3) # => 5
Scala
val add2 = (x: Int) => x + 2
add2(5) /* => 7 */
Obviously, these are trivial examples, but in production code, I usually think of an anonymous function being a one off function that I need for a specific use case (think higher kinded types and the like).
Can anyone explain why I would assign an anonymous function to a variable? Is it a runtime/compile time thing? Are there certain performance characteristics that make this favorable?
I think the way it is presented is more so the reader truly understands that functions are first class in said languages. Had they only used them as arguments to other functions, perhaps the point might be lost. But using them in a very value like way, as the right hand of an assignment, or calling a method on the lambda itself etc drives home the point that these are quite similar to numbers, strings, maps or any other value in the language.
Personally, I don't use this pattern because as other comments have mentioned, it makes code harder to read and debug, as well as in some me cases not having the full power of proper function declaration (Python).
However, when one is writing code which actually makes use of function arguments, one is more or less doing just that. Only the assignment happens more indirectly than the usage of the operator.
According to the Python Docs:
Semantically, they are just syntactic sugar for a normal function definition.
afaik, there are no special performance characteristics for lambda that makes it favourable. If you are thinking of using lambdas for complex tasks, think again, use functions.
Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier.
Edit: Added StefanS' suggestion
In Clojure, the reason is so you can use the function in more than one place. In fact
(defn add2 [x] (+ x 2)
is just shorthand for
(def add2 (fn [x] (+ x 2))
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
given a string "A & B & C" with values of A,B abd C = 0,0,1 respectively, it would be solved as 0 & 0 & 1 to give a result of 0.
I am writing a program where I want to check for & and | for logic operation to return the result.
in this case, I wish to have something like this logic = and. But unfortunately and is a python reserved keyword and it will throw the error below;
File "<ipython-input-248-9d5aa5c6e082>", line 1
logic = and
^
SyntaxError: invalid syntax
How do I fix this?
You can't use a keyword in this way. You might think that you could use the built-in module operator to achieve your goal. This module contains functions that have the same behaviour as the built-in operators, and you can store a reference to one of those functions.
However, logical and and or are missing from this module (and_ and or_ are bitwise). This is probably because these operators exhibit "short-circuit" behaviour, which can't be emulated in a function call.
If it's okay for you not to have short-circuiting, it's trivial to implement these functions yourself:
>>> and_ = lambda a, b: a and b
>>> logic = and_
>>> logic(True, False)
False
>>> logic(True, True)
True
The difference between functions and operators in python is that functions are objects and operators are not. What this means is that and is not a "thing" in python that you can pass around the way you could pass around a value or a function or an object or a class.
You could pass around "the idea of and", by encapsulating it in a function:
and_logic = lambda x, y: a and b
This means that you'd now have a function which, for any a and b returns the logical result of a and b. This function could now be passed around in potentially useful or interesting ways.
But since you don't give a lot of information about what you want to do in your question, it's hard to be more specific about what you can do with this idea.
EDIT: Just after I submitted this, I learned something from #Thomas' post. Apparently, the work of creating the lambda has been done for you!
Yes, of course. You can do almost fancy things by using Python.
>>> import operator
>>> op = operator.or_
>>> print(op(1, 2))
3
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I have a function in Python, and in that same function i have multiple if statements. Lets say i want to return a value from my function. I create a local variable and change it in if statements. Problem is i need it to be defined in function so it works in every if statement, but unlike in C i cant use int a, b, c; but instead i have to give them a value. Problem is that value is going to be recognized if none of the if statements are true.
One clear solution is to take in global values as parameters of the function but i dont want to do that because i dont need their value i only want to change it.
velocity = 5
distance = 6
def calc(distance):
# i would need to say velocity = 5 here
distance + velocity # this does nothing but uses velocity so code cant run
if distance < 7 : # without defining velocity first (in first comment)
velocity = 6
elif distance < 10:
velocity = 7
return velocity
If you really don't want velocity to be a parameter of the function then build an object that has velocity as member variable and calc as method.
When writing Python functions, it is a good idea to strive to follow the following design principles, which come from functional programming.
A function's output should only depend on its inputs. That means that everything that influences the result should be a parameter of the function. This is generally easy to do, and makes the function self-documenting. When you write def foo(x, y, z), it is immediately obvious that the result depends on x, y and z.
A function preferably should only return its output. So it should not use global to modify variables outside of its scope, nor should it modify mutable arguments. (This cannot always be achieved in practice, but it is good to strive for.)
The main advantage is that such functions can be tested and debugged apart from the rest of the application, making those tasks much easier.
In this case,
def calc(distance)
should be:
def calc(distance, velocity)
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
So a few days ago we got this exercise where we need to make a function that takes two lists as input and calculates the difference of their averages.
Sounds simple enough, but there are a few catches:
the entire thing needs to be one line long
you can absolutely NOT use ':'
They encouraged us to use 'import', 'help()' and 'dir()'.
The thing is that I know how to make it only one line long, but the no ':' is really annoying.
The way I see it, I first need to define a function (without code) then change it's 'func_code' attr.
Any ideas on how can I do it?
And how do the params fit into this?
Any answer is appreciated!!!
Edit: thanks for all the answers and the creative minds that said char(58) is the solution, it is really creative and I haven't thought of that solution but it's not allowed since you are using ':' even though not directly.
No : means you can't use lambda. That leaves higher-order functions or eval trickery.
eval('lambda a,b{}sum(a)/len(a)-sum(b)/len(b)'.format(chr(58)))
This meets the letter of the law, but violates its spirit.
Unfortunately, without a function composition function, higher-order functions don't work very well. Implementing one without : is tricky.
Here's what should be a fairly self-contained solution, using a pickled code object. I've created it in Python 3.6, and the specific bytestring is very likely to be version specific, but you can create your own version pretty easily using the expanded code below. Anyway, here's the oneliner:
f = __import__('types').FunctionType(__import__('pickle').loads(b'\x80\x03cipykernel.codeutil\ncode_ctor\nq\x00(K\x02K\x00K\x02K\x04KCC t\x00|\x00\x83\x01t\x01|\x00\x83\x01\x1b\x00t\x00|\x01\x83\x01t\x01|\x01\x83\x01\x1b\x00\x18\x00S\x00q\x01N\x85q\x02X\x03\x00\x00\x00sumq\x03X\x03\x00\x00\x00lenq\x04\x86q\x05X\x01\x00\x00\x00aq\x06X\x01\x00\x00\x00bq\x07\x86q\x08X\x1e\x00\x00\x00<ipython-input-1-384cc87bd499>q\tX\x16\x00\x00\x00difference_of_averagesq\nK\x01C\x02\x00\x01q\x0b))tq\x0cRq\r.'), globals())
Here's what I'm doing without the one-line shenanigans:
import types # replace these import statements with calls to __import__ in the oneliner
import pickle
def difference_of_averages(a, b):
return sum(a)/len(a) - sum(b)/len(b)
payload = pickle.dumps(difference_of_averages.__code__) # embed as a literal in the oneliner
f = types.FunctionType(pickle.loads(payload), globals())
Hmm, having tried this on the few different interpreters I have at hand, it looks like my pickle string includes some nonsense from the IPython interpreter I created it in. If you get errors using my string, I'd suggest just building your own (which, if it contains any junk, will at least be junk compatible with your environment).
Not using ':' is tricky because you normally use it to define the function body, like this:
def average(number_list):
return sum(number_list) / len(number_list)
However, I know of one way to define a function that doesn't require require writing a block for its body: You can assign a lambda function (or even an already-defined function) to a function you want to define, simply by using the equal sign (=). For example, if you want to create an average() function, you might write:
average = lambda number_list: sum(number_list) / len(number_list)
average might look like a variable, but you can use it as a function. It simply calls the lambda function that takes a number_list as input and returns the average value of the number_list. You can call it like this:
value = average([10, 11, 12]) # sets value to 11
Now, lambda functions can only have one line. But that's not really a problem for you, since your task requires you to only use one line.
Do you understand what to do now? Your exercise requires you to find the average of two lists, so you might consider using a lambda function that takes two inputs (instead of just one, like in the example I gave above). Also bear in mind that you need to return the difference, and if the difference should always be positive, consider using Python's abs() function somewhere in your code.
Edit: Well, gilch's response made me realize that I can't use lambda because even they use :. So apparently you can't use my advice. It's still good to know about lambda functions, though.
The fact that you are encouraged to use import makes me wonder if it's okay for you to use an already-defined function from some module to define your own function. Kind of like this:
import math; average = math.difference_of_averages
However, that depends on you being able to find a (probably standard) function that does exactly what you want. (I've briefly checked the math and numpy modules, and haven't found anything that matches yet.)
And maybe this means that you can create a module and define it anyway you like. The module is in its own world, so it's not constrained to the rules of your exercise.
Then again, maybe not.
So unless you want to "sneak-in" a : in an eval statement (as gilch suggested), like this:
average = eval('lambda number_list' + chr(58) + ' sum(number_list) / len(number_list)')
there's no way I know of off hand to avoidi using :.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I know that PEP8 dictates to not assign lambda to an expression because it misses the entire point of a lambda function.
But what about a recursive lambda function? I've found that in many cases, it's really simple, clean and efficient to make a recursion with lambda assigning it to an expression instead of defining a function. And pep8 doesn't mention recursive lambda.
For example, let's compare a function that returns the greatest common divisor between two numbers:
def gcd(a,b):
if b == 0:
return a
return gcd(b, a % b)
vs
gcd = lambda a, b: a if b == 0 else gcd(b, a % b)
So, what should I do?
You have "cheated" a bit in your question, since the regular function could also be rewritten like this:
def gcd(a,b):
return a if b == 0 else gcd(b, a % b)
Almost as short as the lambda version, and even this can be further squeezed into a single line, but at the expense of readability.
The lambda syntax is generally used for simple anonymous functions that are normally passed as arguments to other functions. Assigning a lambda function to a variable doesn't make much sense, it is just another way of declaring a named function, but is less readable and more limited (you can't use statements in it).
A lot of thought has been put into PEP8 and the recommendations in it are there for a reason, thus I would not recommend deviating from it, unless you have a very good reason for doing so.
Go with the normal function definition. There's absolutely no benefit of using lambda over def, and normal function definition is (for most people) much more readable. With lambda, you gain nothing, but you often lose readability.
I would recommend you to read this answer. Recursion doesn't change anything. In fact, in my opinion, it favours normal def even more.
If you assign a lambda to a variable, you won't be able to pass it as an argument nor return it in the same line, which is the exact purpose of lambda.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
Paul Graham describes the following problem:
We want to write a function that generates accumulators-- a function that takes a number n, and returns a function that takes another number i and returns n incremented by i.
He says that whereas such a function could be implemented in Lisp/Ruby/Perl as simply as something like
(defun foo (n)
(lambda (i) (incf n i)))
, in Python it would be written
class foo:
def __init__(self, n):
self.n = n
def __call__(self, i):
self.n += i
return self.n
So my question is, What exactly about Python (apart from the lack of support for multi-line lambdas) prevents you from implementing an accumulator generator in the terse style of the first code sample above? Would Python ever support such a thing in the future, as Paul Graham speculates?
The example if first of all contrived. After defining the accumulator, you would in Python use it like this:
acc = foo(6)
acc(2)
acc(4)
For what use? In Python you would do this:
acc = 6
acc += 2
acc += 4
I don't know if defining an accumulator in lisp makes sense, but in Python you don't need to define one, because you would have it built in, so to speak.
Second of all the question you ask hits the nail on the head. What prevents Python from doing this in a "terse" style? Because the attitude of Python is that it will going to be a language that is quick to develop in and that is maintainable, and that means easy to read. Code golf and obtuse, terse code is not a part of what Python is designed for.
But ultimately, the reason Python will never evolve this functionality is that is relies on integers being mutable, ie that you can do something like:
>>> g = 6
>>> g++
>>> g
7
This will not happen in Python, where integers are immutable. You can't increase the value of an integer. This simplifies both the language and it's use a lot. For example, if integers were mutable, they could not be used as keys in dictionaries.
Essentially the example centers around increasing the value of integers, something you can't do in Python. In Python, when you add two integers you get a third integer back. You do not increase the value of the first one.
So Python will never become lisp, and only people who have used lisp for too long thinks it should, or persist in the "python is almost lisp" idiom. And it can't do an accumulator in just a few lines, because it neither needs to nor wants to.
He actually describes one reason in his followup post. His brief discussion there covers both of the reasons I mention below, although his take on it is a bit different.
As he talks about earlier in the post, part of what he's concerned with is the difference between statements and expressions. In Python += is a statement, and lambdas cannot contain statements, only expressions.
However, there's another issue. He wants his function to take "a number" as input, but he makes a distinction between "plus" and "increment" (as do many programming languages). However, my own position would be that there is no such distinction for numbers, only for variables (or "objects" or similar things). There is no such thing as "incrementing" the number 5. In this sense, you still can't write a Python lambda that increments a variable containing a builtin in numeric type, but you can do it if it accepts a mutable object instead of a raw number. And you could write your own MutableNumber class that works this way and make it totally interoperable with existing numeric types. So in this sense the reason Python doesn't support has to do with the design of its types (i.e., numbers are immutable) rather than the sort of functional issues he discusses in the post.
Whether any of this is actually a problem for the language is, of course, another question.
It can. The trick is to use a container to hold the original integer and to set and access this number without using the assignment operator.
>>> g=lambda n: (lambda d: lambda i: (d.__setitem__('v', d['v']+i),d['v'])[1])({'v': n})
>>> x=g(3)
>>> x(1)
4
>>> x(1)
5
>>> x(10)
15
>>>
trying to do this as clear as I could, separating lambdas to variables:
concat = lambda arr, val: (arr.append(val), arr)[1]
f = lambda n: (lambda i: concat(n,n.pop(0)+i)[0])
accumulate = lambda n: f([n])
a=accumulate(9)
a(1) #10
a(2) #12