# [Python] lambda Vs. def

Recently, while solving math problems for many hours I ended up getting sick of solving simple calculation at the end of one problem,
so I tried making a simple python automation programme for calculations.
It was mostly about putting multiple values into a function and finding the values that make the function return 0.
In the code, I was overusing lambda expression for every function I had to define.

However, some of those lambda functions I used were inside a `for loop`

, which makes the code smelly! (Needs to be Refactored!)

This is the part of the code that smells a lot.

```
nominator = [1, 2, 3, 4]
denominator = [1, 3]
for d in denominator:
for u in nominator:
frac = nominator/denominator
func = lambda x: 3*(x**4) -29*(x**2) + 8
if not func(frac):
print(nominator, denominator)
print("no solution found")
```

Yes I’m telling you. I was pretty dumb at the moment :(

After figuring that out,
I became quite curious about the performance between `lambda`

and `def`

,
and how they behaviour differently in the back side of the high level programming language, python.
What I meant by its performance is mainly as to time it takes to perform a certain task and user-usability (which one is easy to use).

### Measuring Time

I have recorded their time taken to complete one task for 100 iterations

```
import time
import matplotlib.pyplot as plt
import numpy as np
lambda_function = lambda x: 3*(x**4) -29*(x**2) + 8
def def_function(x):
return 3*(x**4) -29*(x**2) + 8
lambdaTime = []
defTime = []
for _ in range(100):
start1 = time.time()
lambda_function(123)
end1 = time.time()
lambdaTime.append(end1-start1)
start2 = time.time()
def_function(123)
end2 = time.time()
defTime.append(end2-start2)
# Graph
fig, ax = plt.subplots()
x = np.array(lambdaTime)
y = np.array(defTime)
plt.scatter(np.arange(100), x, marker='o', label='lambda')
plt.scatter(np.arange(100), y, marker='^', label='def')
ax.set_xlabel("iteration")
ax.set_ylabel("def time & lambda time")
ax.set_xlim(0, 100)
ax.set_ylim(min(min(defTime, lambdaTime))-np.mean(defTime), max(max(defTime, lambdaTime))+np.mean(defTime))
ax.legend(
loc='best',
shadow=True,
fancybox=True,
borderpad=1
)
plt.show()
```

This Image shows that they have the same time-wise performance.

### Bytecode disassembling

```
import dis
lambda_function = lambda x: 3*(x**4) -29*(x**2) + 8
def def_function(x):
return 3*(x**4) -29*(x**2) + 8
# bytecode disassemble
print("Lambda")
dis.dis(lambda_function)
print("def")
dis.dis(def_function)
```

Terminal output:

```
Lambda
6 0 LOAD_CONST 1 (3)
2 LOAD_FAST 0 (x)
4 LOAD_CONST 2 (4)
6 BINARY_POWER
8 BINARY_MULTIPLY
10 LOAD_CONST 3 (29)
12 LOAD_FAST 0 (x)
14 LOAD_CONST 4 (2)
16 BINARY_POWER
18 BINARY_MULTIPLY
20 BINARY_SUBTRACT
22 LOAD_CONST 5 (8)
24 BINARY_ADD
26 RETURN_VALUE
def
9 0 LOAD_CONST 1 (3)
2 LOAD_FAST 0 (x)
4 LOAD_CONST 2 (4)
6 BINARY_POWER
8 BINARY_MULTIPLY
10 LOAD_CONST 3 (29)
12 LOAD_FAST 0 (x)
14 LOAD_CONST 4 (2)
16 BINARY_POWER
18 BINARY_MULTIPLY
20 BINARY_SUBTRACT
22 LOAD_CONST 5 (8)
24 BINARY_ADD
26 RETURN_VALUE
```

They do generate the same bytecode!

## Leave a comment