Last active
March 18, 2019 03:35
-
-
Save phanhaiquang/5aa20b7b5588809af4878d744cfd268b to your computer and use it in GitHub Desktop.
Python function programming
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/python | |
# copied from https://udemy.com/learning-path-python-functional-programming-with-python/learn/v4/t/lecture/8723246?start=0 | |
from math import sqrt | |
##### List ##### | |
# loop | |
a = [sqrt(i) for i in range(5)] | |
a = map(sqrt, range(5)) | |
# nested loop | |
[(x, y) for x in range(2) for y in range(2)] | |
# filtering | |
b = [i for i in range(5) if i%2] | |
b = filter(lambda i: not i%2, range(5)) | |
##### Dict ##### | |
# loop | |
{k.capitalize(): v:capitalize() for k, v in var} | |
# filtering | |
{k.capitalize(): v:capitalize() for k, v in var if k != 'ignored'} | |
##### Generator ##### | |
g = (sqrt(i) for i in range(5)) | |
# filtering | |
g = (sqrt(i) for i in range(5) if not i%2) | |
# break with condition | |
class EndGenerator(Exception): pass | |
def stop(): | |
raise EndGenerator() | |
def wrap(g): | |
l = [] | |
while True: | |
try: | |
l.append(next(g)) | |
except EndGenerator: | |
break | |
return l | |
g = wrap(i for i in fibonacci() if i < 10 or stop()) | |
# when i >= 10, "stop" func is executed | |
# it generates an exception that is catched by "wrap" func |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/python | |
import functools as ft | |
import itertools as it | |
OPERATORS = '+', '-', '*', '/' | |
EXIT_COMMANDS = 'exit', 'quit' | |
def can_calculate(state): | |
if len(state) < 3: | |
return False | |
*_, i1, op, i2 = state | |
return isinstance(i, float) and op in OPERATORS and isinstance(i2, float) | |
def calculate(state): | |
*_, i1, op, i2 = state | |
if op == '+': | |
result = i1 + i2 | |
elif op == '-': | |
result = i1 - i2 | |
elif op == '*': | |
result = i1 * i2 | |
elif op == '/': | |
result = i1 / i2 | |
else | |
raise ValueError('Invalid operator') | |
print('%f %s %f = %f' % (i1, op, i2, result)) | |
result result | |
def process_input(state, update): | |
state.append(update) | |
if can_calculate(state): | |
result = calculate(state) | |
state.append(result) | |
return state | |
def validate_input(func): | |
def inner(): | |
i = func() | |
try: | |
i = float(i) | |
except ValueError: | |
pass | |
if isinstance(i, float) or i in OPERATORS or i in EXIT_COMMANDS: | |
return i | |
return None | |
return inner | |
@validate_input | |
def get_input(): | |
return input() | |
def input_loop(): | |
while True: | |
i = get_input() | |
if i in EXIT_COMMANDS: | |
break | |
if i is None: | |
print('Please enter a number or an operator') | |
continue | |
yield i | |
def calculator(): | |
ft.reduce(process_input, input_loop(), [0]) | |
calculator() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/python | |
any() : checks if any element is True | |
all() : checks if all element is True | |
sorted() : | |
min() : | |
max() : | |
sum() : | |
##### itertools module ##### | |
count(start, step) : infinite range | |
cycle() : loops iterator infinitely | |
stop it by zip & range == zip(range(20), cycle(str)) | |
repeat() : create infinite iterator from a single element | |
zip(range(10), repeat(str)) | |
chain() : links multiple iterators tail to head | |
chain('abc', [1, 2, 3], 'def') | |
compress() : filters an iterator based on a list of selectors | |
sentence = 'iterators', "don't", 'rock' | |
selector = True, False, True | |
compress(sentence, selector) | |
takewhile() : takes elements until a criterion is satisfied | |
for i in takewhile(lambda x: x < 10, count()) | |
== range(10) | |
dropwhile() : skips elements while a criterion is satisfied | |
for i in dropwhile(lambda x: x < 5, count()) | |
== 5, 6, ... | |
groupby() : split an interator into multiple iterators based on a grouping key | |
is_even = lambda x: not x%2 | |
for e, g in groupby( | |
sorted(range(10), key=is_even), | |
key=is_even | |
) | |
product() : returns cartesian product of two iterators like a nested loop | |
product([0, 1, 2], [3, 4, 5]) = [ [0, 3], [0, 4], [0, 5], [1, 3], .... ] | |
permutations() : returns ALL possible different orders of the elements | |
permutations([1, 2, 3]) = [ [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1],... ] | |
combinations(l, r) : returns all possible ways that takes "r" elements from "l" | |
combinations([1,2,3], r=2): [ [1, 2], [1, 3], [2, 3] ] | |
##### functools module ##### | |
import functools as ft | |
partial() : bind a "argument" to a "function" | |
partial(func, arg) | |
reduce(func, iterable [,init state]) : apply "func" of two arguments from LEFT to RIGHT | |
reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5) | |
@ : decorator = apply func on hier order of another | |
def runtime(func): | |
t_start = time.time() | |
func() | |
t_end = time.time() | |
return t_end - t_start | |
@runtime --> apply decorator here | |
def myfunc(): | |
doing something | |
@ft.lru_cache() : decorator remembers the results of a function call, and | |
when the function is called again with SAME set of arguments, | |
returns this result right aways | |
@singledispatch() : decorator allows you to create different implementations of a function, given different argument types. | |
The type of the first argument is used to decide which implementation of the function should be used | |
@ft.singledispatch | |
def add(a, b): --> func 1 | |
return a+b # '1' + '2' = '12' | |
@add.register(str) | |
def _(a, b): --> func 2 | |
return int(a)+int(b) # 1 + 2 = 3 | |
--> at this point of time, there are 2 "add" function | |
add('1', '2') will take 1st arg ('1') to select "func 2" | |
add(1, 2) will take 1st arg (1) to select "func 1" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment