Python: how to make functions in arrays - python

I am trying to make my code a bit more dynamic and smaller so I am trying to use some arrays, but I need to put a function in a array. I heard of the lambda but the problem is that it doesnt need to return any value but it does need to set a value. this is what I tried but didn't work:
variableArray = [lambda: value = '2' if variable == 1 else None,lambda: value = '3' if variable == 1 else None]
for k in range(len(variableArray)):
print(variableArray[k](2))
but I can't set a value with this methode and I wasn't abled to find any other methodes. so are there any other methodes that would work with what I am trying to do?

Python distinguish between expressions and statements (and here compound statements). Expressions can not contain any statements. An assignment is a statement. lambdas are expressions, hence there's no way to use a lambda with that syntax.
However using normal defs wouldn't change much:
def function():
value = '2' if variable == 1 else None
Here the function is creating a new local variable value, assigning it the its value and then removing it. If you want to modify a non-local variable you must declare it as global:
def function():
global value
value = '2' if variable == 1 else None
Note that you can put functions defined with defs into a list:
some_list = [function, #other functions]
However you should try to avoid using global variables as much as you can.
You should prefer function parameters and return values to communicate between the function and the rest of the program.
In particular you probably wanted to write functions such as:
variableArray = [lambda arg: '2' if arg == 1 else None, lambda arg: '3' if arg == 1 else None]
You can then do:
for func in variableArray:
value = func(2)
This will have the same effect as your code.
Note that the lambdas should have a parameter, otherwise calling them with the (2) will raise an error.

Functions in arrays is possible. But you can't put assignments in lambdas. And your lambda isn't taking any arguments, despite passing 2 into them.
And for k in range(len(variableArray)): is wasteful bad form. Try just:
for k in variableArray:
print(k(2))
As for the functions, maybe you want this?
variableArray = [lambda x: '2' if x == 1 else None, lambda x: '3' if x == 1 else None]

It's not entirely clear what you need, but maybe this is closer to what you're after.
If you want to get a list of values from the list of functions, passing a single argument into the function-list, try this:
functions = [lambda x: '2' if x == 1 else None, lambda x: '3' if x == 1 else None]
values = [function(2) for function in functions]

Related

Can a function using a global variable use the variable's value from when the function was declared rather than when it was called?

Here is a very simplified example of what I am trying to do:
x = 3
def f():
print(x)
x = 5
f() #f prints 5 but I want it to print 3.
Is there a way, when declaring the function, to turn x into a constant that points somewhere other than the global variable x? I can't provide arguments to the function.
This is a pretty common trick (you usually see it in lambda expressions that want to bind a particular value within a loop):
x = 3
def f(x=x):
print(x)
x = 5
f() # prints 3
The trick is that default parameter values are evaluated at the time of function definition, so in the expression x=x, the x on the right hand side is evaluated (producing the value 3) and then stored as the default value of the x parameter in the function (which shadows the x in the outer scope).
You could equivalently write:
x = 3
def f(n=x):
print(n)
x = 5
f() # prints 3
which has the same result, but doesn't shadow the x variable.
From what I understand, you seem to want x to hold two values simultaneously - which is what complex data structures are for. A list would work fine, or a dict:
>>> x = [3]
>>> def f():
... print(x[0]) # always refers to first element. Functionally constant.
...
>>> x.append(5)
>>> f()
3
>>>
However, it sounds like you really have an XY problem, where you're asking about your solution instead of your actual problem. Go back to your code and check if this seems to be the case. If so, we might be able to point you towards a better way of solving your real issue.

Control Structures and Functions inside lambda

Create a lambda function greater, which takes two arguments x and y and return x if x>y otherwise y. input value is (9,3)
greater= lambda a,b:a>b
if a>b:
print(a)
else:
return b
print(greater(a,b))
File "/code/source.py3", line 11
return b
^
SyntaxError: 'return' outside function
Even I am getting error in return statement.
I have to only get the output as value but I am getting value with True.
Use if - else in lambda:
greater = lambda a, b: a if a > b else b
and call it as:
greater(9, 13)
Problems with your code:
Your lambda function just compares two variables and returns a True / False.
You used return outside a function which is not allowed. (Btw, there is no need of explicit if - else outside lambda when you can do within).
You don't return from a lambda function.
greater = lambda a,b: a if a > b else b
print(greater(3,4))
You can use ternary operators (a if a > b else c) in lambdas but control structures require the def keyword
Also, there is no return in a lambda function
Use a ternary if in your lambda:
greater = lambda x,y: x if x>y else y
greater(1,3) # 3
greater(4,3) # 4
Small anonymous functions can be created with the lambda keyword. Lambda functions can be used wherever function objects are required. They are syntactically restricted to a single expression.
Read more.
Solution without using ternary expression:
greater = lambda a, b: (a, b)[a<b]
a<b returns the boolean value False if a is greater than, or equal to, b, and True if a is smaller than b. We use the boolean value (basically representing 0 or 1) as an index to the tuple (a, b) to return our desired result.

if and else in python lambda expression

Please help me to understand how this works. Output is 4
a=4
b=7
x=lambda: a if 1 else b
lambda x: 'big' if x > 100 else 'small'
print(x())
First, let's remove this line as it doesn't do anything:
lambda x: 'big' if x > 100 else 'small'
This lambda expression is defined but never called. The fact that it's argument is also called x has nothing to do with the rest of the code.
Let's look at what remains:
a = 4
b = 7
x = lambda: a if 1 else b
print(x())
Here x becomes a function as it contains code. The lambda form can only contain expressions, not statements, so it has to use the expression form of if which is backward looking:
true-result if condition else false-result
In this case the condition is 1, which is always true, so the result of the function x() is always the value of a, assigned to 4 earlier in the code. Effectively, x() acts like:
def x():
return a
Understanding the differences between expressions and statements is key to understanding code like this.
Your x is always equals to 4, as it takes no arguments and if 1 is always True.
Then you have lambda expression that's not assigned to any variable, neither used elsewhere.
Eventualy, you print out x, which is always 4 as I said above.
P.S. I strongly suggest you to read Using lambda Functions from Dive into Python
Let me translate that for you.
You assign to x a lambda function with no arguments. Because 1 always evaluates as true, you always return the externally defined variable a, which evaluates as 4.
Then, you create a lambda function with one argument x, which you don't assign to a variable/access name, so it is lost forever.
Then, you call function x, which always returns a. Output is 4.

E731 do not assign a lambda expression, use a def

I get this pep8 warning whenever I use lambda expressions. Are lambda expressions not recommended? If not why?
The recommendation in PEP-8 you are running into is:
Always use a def statement instead of an assignment statement that
binds a lambda expression directly to a name.
Yes:
def f(x): return 2*x
No:
f = lambda x: 2*x
The first form means that the name of the resulting
function object is specifically 'f' instead of the generic '<lambda>'.
This is more useful for tracebacks and string representations in
general. The use of the assignment statement eliminates the sole
benefit a lambda expression can offer over an explicit def statement
(i.e. that it can be embedded inside a larger expression)
Assigning lambdas to names basically just duplicates the functionality of def - and in general, it's best to do something a single way to avoid confusion and increase clarity.
The legitimate use case for lambda is where you want to use a function without assigning it, e.g:
sorted(players, key=lambda player: player.rank)
In general, the main argument against doing this is that def statements will result in more lines of code. My main response to that would be: yes, and that is fine. Unless you are code golfing, minimising the number of lines isn't something you should be doing: go for clear over short.
Here is the story, I had a simple lambda function which I was using twice.
a = map(lambda x : x + offset, simple_list)
b = map(lambda x : x + offset, another_simple_list)
This is just for the representation, I have faced couple of different versions of this.
Now, to keep things DRY, I start to reuse this common lambda.
f = lambda x : x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)
At this point my code quality checker complains about lambda being a named function so I convert it into a function.
def f(x):
return x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)
Now the checker complains that a function has to be bounded by one blank line before and after.
def f(x):
return x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)
Here we have now 6 lines of code instead of original 2 lines with no increase in readability and no increase in being pythonic. At this point the code checker complains about the function not having docstrings.
In my opinion this rule better be avoided and broken when it makes sense, use your judgement.
Lattyware is absolutely right: Basically PEP-8 wants you to avoid things like
f = lambda x: 2 * x
and instead use
def f(x):
return 2 * x
However, as addressed in a recent bugreport (Aug 2014), statements such as the following are now compliant:
a.f = lambda x: 2 * x
a["f"] = lambda x: 2 * x
Since my PEP-8 checker doesn't implement this correctly yet, I turned off E731 for the time being.
I also encountered a situation in which it was even impossible to use a def(ined) function.
class SomeClass(object):
# pep-8 does not allow this
f = lambda x: x + 1 # NOQA
def not_reachable(self, x):
return x + 1
#staticmethod
def also_not_reachable(x):
return x + 1
#classmethod
def also_not_reachable(cls, x):
return x + 1
some_mapping = {
'object1': {'name': "Object 1", 'func': f},
'object2': {'name': "Object 2", 'func': some_other_func},
}
In this case, I really wanted to make a mapping which belonged to the class. Some objects in the mapping needed the same function. It would be illogical to put the a named function outside of the class.
I have not found a way to refer to a method (staticmethod, classmethod or normal) from inside the class body. SomeClass does not exist yet when the code is run. So referring to it from the class isn't possible either.
This works for me in a class, remove lambda expression and use def instead, changing this...
def set_every(self, every: int = 1, time_unit: int = TimeUnit.Day):
every_func = lambda x: "*" if x == 1 else "*/" + str(x)
if TimeUnit.has_value(time_unit):
self.month_of_year = "*"
self.day_of_month = "*" if time_unit != TimeUnit.Day else every_func(every)
self.day_of_week = "*" if time_unit != TimeUnit.Week else every_func(every)
by this...
def set_every(self, every: int = 1, time_unit: int = TimeUnit.Day):
def every_func(x: int) -> str: return "*" if x == 1 else "*/" + str(x)
if TimeUnit.has_value(time_unit):
self.month_of_year = "*"
self.day_of_month = "*" if time_unit != TimeUnit.Day else every_func(every)
self.day_of_week = "*" if time_unit != TimeUnit.Week else every_func(every)

Python functions within lists

So today in computer science I asked about using a function as a variable. For example, I can create a function, such as returnMe(i) and make an array that will be used to call it. Like h = [help,returnMe] and then I can say h1 and it would call returnMe("Bob"). Sorry I was a little excited about this. My question is is there a way of calling like h.append(def function) and define a function that only exists in the array?
EDIT:
Here Is some code that I wrote with this!
So I just finished an awesome FizzBuzz with this solution thank you so much again! Here's that code as an example:
funct = []
s = ""
def newFunct(str, num):
return (lambda x: str if(x%num==0) else "")
funct.append(newFunct("Fizz",3))
funct.append(newFunct("Buzz",5))
for x in range(1,101):
for oper in funct:
s += oper(x)
s += ":"+str(x)+"\n"
print s
You can create anonymous functions using the lambda keyword.
def func(x,keyword='bar'):
return (x,keyword)
is roughly equivalent to:
func = lambda x,keyword='bar':(x,keyword)
So, if you want to create a list with functions in it:
my_list = [lambda x:x**2,lambda x:x**3]
print my_list[0](2) #4
print my_list[1](2) #8
Not really in Python. As mgilson shows, you can do this with trivial functions, but they can only contain expressions, not statements, so are very limited (you can't assign to a variable, for example).
This is of course supported in other languages: in Javascript, for example, creating substantial anonymous functions and passing them around is a very idiomatic thing to do.
You can create the functions in the original scope, assign them to the array and then delete them from their original scope. Thus, you can indeed call them from the array but not as a local variable. I am not sure if this meets your requirements.
#! /usr/bin/python3.2
def a (x): print (x * 2)
def b (x): print (x ** 2)
l = [a, b]
del a
del b
l [0] (3) #works
l [1] (3) #works
a (3) #fails epicly
You can create a list of lambda functions to increment by every number from 0 to 9 like so:
increment = [(lambda arg: (lambda x: arg + x))(i) for i in range(10)]
increment[0](1) #returns 1
increment[9](10) #returns 19
Side Note:
I think it's also important to note that this (function pointers not lambdas) is somewhat like how python holds methods in most classes, except instead of a list, it's a dictionary with function names pointing to the functions. In many but not all cases instance.func(args) is equivalent to instance.__dict__['func'](args) or type(class).__dict__['func'](args)

Categories