O GoConqr está de visual novo! Conte para nós o que você achou.

Flashcards

016_Functions

Serhii Yurskyi Python Advanced Inglês 198 flashcards

Flashcards do conjunto (198)

  1. 1Defining a function and calling itdef func():
    pass
    def func():
    print("Текст до инструкции return")
    return "Возвращаемое значение"
    print("Эта инструкция никогда не будет выполнена")
    print(func()) # Вызываем функцию
  2. 2Function definitionsdef print_ok():
    """ Пример функции без параметров """
    print("Сообщение при удачно выполненной операции")
    def echo(m):
    """ Пример функции с параметром """
    print(m)
    def summa(x, y):
    """ Пример функции с параметрами,
    возвращающей сумму двух переменных """
    return x + y
  3. 3Callback functiondef summa(x, y):
    return x + y
    def func(f, a, b):
    """ Через переменную f будет доступна ссылка на
    функцию summa() """
    return f(a, b) # Вызываем функцию summa()
    # Передаем ссылку на функцию в качестве параметра
    v = func(summa, 10, 20)
    def summa(x, y):
    """ Суммирование двух чисел """
    return x + y
    dir(summa)
    summa.__name__
    summa.__code__.co_varnames
    summa.__doc__
  4. 4Definition of functions depending on conditionsn = input("Введите 1 для вызова первой функции: ")
    if n == "1":
    def echo():
    print("Вы ввели число 1")
    else:
    def echo():
    print("Альтернативная функция")
    echo() # Вызываем функцию
    input()
    def echo():
    print("Вы ввели число 1")
    def echo():
    print("Альтернативная функция")
    echo() # Всегда выводит "Альтернативная функция"
  5. 5Optional parametersdef summa(x, y=2): # y — необязательный параметр
    return x + y
    a = summa(5)
    # Переменной a будет присвоено значение 7
    b = summa(10, 50) # Переменной b будет присвоено значение 60
    def summa(x, y):
    return x + y
    print(summa(10, 20)) # Выведет: 30
  6. 6Key Matchingdef summa(x, y):
    return x + y
    print(summa(y=20, x=10)) # Сопоставление по ключам
    def summa(a=2, b=3, c=4): # Все параметры являются необязательными
    return a + b + c
    print(summa(2, 3, 20)) # Позиционное присваивание
    print(summa(c=20)) # Сопоставление по ключам
  7. 7Example of passing values ​​from… tuple and listdef summa(a, b, c):
    return a + b + c
    t1, arr = (1, 2, 3), [1, 2, 3]
    print(summa(*t1)) # Распаковываем кортеж
    print(summa(*arr)) # Распаковываем список
    t2 = (2, 3)
    print(summa(1, *t2)) # Можно комбинировать значения
  8. 8Example of transferring values ​​f…the dictionarydef summa(a, b, c):
    return a + b + c
    d1 = {"a": 1, "b": 2, "c": 3}
    print(summa(**d1)) # Распаковываем словарь
    t, d2 = (1, 2), {"c": 3}
    print(summa(*t, **d2)) # Можно комбинировать значения
    def func(a, b):
    a, b = 20, "str"
    x, s = 80, "test"
    func(x, s) # Значения переменных x и s не изменяются
    print(x, s) # Выведет: 80 test
    def func(a, b):
    a[0], b["a"] = "str", 800
    x = [1, 2, 3] # Список
    y = {"a": 1, "b": 2} # Словарь
    func(x, y) # Значения будут изменены!!!
    print(x, y) # Выведет: ['str', 2, 3] {'a': 800, 'b': 2}
  9. 9Passing a variable object in a functiondef func(a, b):
    a = a[:] # Создаем поверхностную копию списка
    b = b.copy() # Создаем поверхностную копию словаря
    a[0], b["a"] = "str", 800
    x = [1, 2, 3] # Список
    y = {"a": 1, "b": 2} # Словарь
    func(x, y) # Значения останутся прежними
    print(x, y) # Выведет: [1, 2, 3] {'a': 1, 'b': 2}
    func(x[:], y.copy())
    def func(a=[]):
    a.append(2)
    return a
    print(func()) # Выведет: [2]
    print(func()) # Выведет: [2, 2]
    print(func()) # Выведет: [2, 2, 2]
    def func(a=None):
    # Создаем новый список, если значение равно None
    if a is None:
    a = []
    a.append(2)
    return a
    print(func()) # Выведет: [2]
    print(func([1])) # Выведет: [1, 2]
    print(func()) # Выведет: [2]
  10. 10Saving transferred data in a tupledef summa(*t):
    """ Функция принимает произвольное количество параметров """
    res = 0
    for i in t: # Перебираем кортеж с переданными параметрами
    res += i
    return res
    print(summa(10, 20)) # Выведет: 30
    print(summa(10, 20, 30, 40, 50, 60)) # Выведет: 210
    def summa(x, y=5, *t): # Комбинация параметров
    res = x + y
    for i in t: # Перебираем кортеж с переданными параметрами
    res += i
    return res
    print(summa(10)) # Выведет: 15
    print(summa(10, 20, 30, 40, 50, 60)) # Выведет: 210
  11. 11Saving the transferred data in the dictionarydef func(**d):
    for i in d: # Перебираем словарь с переданными параметрами
    print("{0} => {1}".format(i, d[i]), end=" ")
    func(a=1, b=2, c=3) # Выведет: a => 1 c => 3 b => 2
  12. 12Combining parameters.def func(*t, **d):
    """ Функция примет любые параметры """
    for i in t:
    print(i, end=" ")
    for i in d: # Перебираем словарь с переданными параметрами
    print("{0} => {1}".format(i, d[i]), end=" ")
    func(35, 10, a=1, b=2, c=3) # Выведет: 35 10 a => 1 c => 3 b => 2
    func(10) # Выведет: 10
    func(a=1, b=2) # Выведет: a => 1 b => 2
    def func(*t, a, b=10, **d):
    print(t, a, b, d)
    func(35, 10, a=1, c=3) # Выведет: (35, 10) 1 10 {'c': 3}
    func(10, a=5) # Выведет: (10,) 5 10 {}
    func(a=1, b=2) # Выведет: () 1 2 {}
    func(1, 2, 3) # Ошибка. Параметр a обязателен!
    def func(x=1, y=2, *, a, b=10):
    print(x, y, a, b)
    func(35, 10, a=1) # Выведет: 35 10 1 10
    func(10, a=5) # Выведет: 10 2 5 10
    func(a=1, b=2) # Выведет: 1 2 1 2
    func(a=1, y=8, x=7) # Выведет: 7 8 1 10
    func(1, 2, 3) # Ошибка. Параметр a обязателен!
  13. 13An example of using anonymous functionsf1 = lambda: 10 + 20 # Функция без параметров
    f2 = lambda x, y: x + y # Функция с двумя параметрами
    f3 = lambda x, y, z: x + y + z # Функция с тремя параметрами
    print(f1()) # Выведет: 30
    print(f2(5, 10)) # Выведет: 15
    print(f3(5, 10, 30)) # Выведет: 45
  14. 14Optional parameters in anonymous functionsf = lambda x, y=2: x + y
    print(f(5)) # Выведет: 7
    print(f(5, 6)) # Выведет: 11
  15. 15An example of using function generatorsdef func(x, y):
    for i in range(1, x+1):
    yield i ** y
    for n in func(10, 2):
    print(n, end=" ") # Выведет: 1 4 9 16 25 36 49 64 81 100
    print() # Вставляем пустую строку
    for n in func(10, 3):
    print(n, end=" ") # Выведет: 1 8 27 64 125 216 343 512 729 1000
  16. 16Using the __next __ () parameterdef func(x, y):
    for i in range(1, x+1):
    yield i ** y
    i = func(3, 3)
    print(i.__next__()) # Выведет: 1 (1 ** 3)
    print(i.__next__()) # Выведет: 8 (2 ** 3)
    print(i.__next__()) # Выведет: 27 (3 ** 3)
    print(i.__next__()) # Исключение StopIteration
  17. 17Calling one generator function fro… (simple case)def gen(l):
    for e in l:
    yield from range(1, e + 1)
    l = [5, 10]
    for i in gen([5, 10]): print(i, end = " ")
  18. 18Calling one function generator fro…er (hard case)def gen2(n):
    for e in range(1, n + 1):
    yield e * 2
    def gen(l):
    for e in l:
    yield from gen2(e)
    l = [5, 10]
    for i in gen([5, 10]): print(i, end = " ")
  19. 19Specifying multiple decoratorsdef deco1(f):
    print("Вызвана функция deco1()")
    return f
    def deco2(f):
    print("Вызвана функция deco2()")
    return f
    @deco1
    @deco2
    def func(x):
    return "x = {0}".format(x)
    print(func(10))
  20. 20Access restriction using decoratorpassw = input("Введите пароль: ")
    def test_passw(p):
    def deco(f):
    if p == "10": # Сравниваем пароли
    return f
    else:
    return lambda: "Доступ закрыт"
    return deco # Возвращаем функцию-декоратор
    @test_passw(passw)
    def func():
    return "Доступ открыт"
    print(func()) # Вызываем функцию
  21. 21Function Python Scope BasicsX = 99
    def func():
    X = 88
    # Global scope
    X = 99 # X and func assigned in module: global
    def func(Y): # Y and Z assigned in function: locals
    # Local scope
    Z = X + Y # X is a global
    return Z
    print(func(1)) # func in module: result=100
  22. 22The global StatementX = 88 # Global X
    def func():
    global X
    X = 99 # Global X: outside def
    func()
    print(X) # Prints 99
    y, z = 1, 2 # Global variables in module
    def all_global():
    global x # Declare globals assigned
    x = y + z # No need to declare y, z: LEGB rule
  23. 23Scopes and Nested FunctionsX = 99 # Global scope name: not used
    print(X)
    def f1():
    X = 88 # Enclosing def local
    def f2():
    print(X) # Reference made in nested def
    f2()
    f1() # Prints 88: enclosing def local
    def f1():
    X = 89
    def f2():
    print(X) # Remembers X in enclosing def scope
    return f2 # Return f2 but don't call it
    action = f1() # Make, return function
    action() # Call it now: prints 88
  24. 24Retaining Enclosing Scope State with Defaultsdef f1():
    x = 88
    def f2(x=x): # Remember enclosing scope X with defaults
    print(x)
    f2()
    f1() # Prints 88
    def f1():
    x = 88 # Pass x along instead of nesting
    f2(x) # Forward reference okay
    def f2(x):
    print(x)
    f1()
  25. 25Nested scopes, defaults, and lambdasdef func():
    x = 4
    action = (lambda n: x ** n) # x remembered from enclosing def
    return action
    x = func()
    print(x(2)) # Prints 16, 4 ** 2
    def func():
    x = 4
    action = (lambda n, x=x: x ** n) # Pass x in manually
    return action
  26. 26nonlocal in Actiondef tester(start):
    state = start # Referencing nonlocals works normally
    def nested(label):
    print(label, state) # Remembers state in enclosing scope
    return nested
    F = tester(0)
    F('spam')
    F('ham')
    def tester(start):
    state = start
    def nested(label):
    print(label, state)
    state += 1 # Cannot change by default (or in 2.6)
    return nested
    F = tester(0)
    # F('spam') # UnboundLocalError: local variable 'state' referenced before assignment
  27. 27Using nonlocal for changesdef tester(start):
    state = start # Each call gets its own state
    def nested(label):
    nonlocal state # Remembers state in enclosing scope
    print(label, state)
    state += 1 # Allowed to change it if nonlocal
    return nested
    F = tester(0)
    print('#' * 52 + ' Increments state on each call')
    F('spam') # Increments state on each call
    F('ham')
    F('eggs')
    print('#' * 52 + ' Make a new tester that starts at 42')
    G = tester(42) # Make a new tester that starts at 42
    G('spam')
    print('#' * 52 + ' My state information updated to 43')
    G('eggs') # My state information updated to 43
    print('#' * 52 + ' ')
    F('bacon') # But F's is where it left off: at 3
    # Each call has different state information
  28. 28Arguments and Shared Referencesdef f(a): # a is assigned to (references) passed object
    a = 99 # Changes local variable a only
    b = 88
    f(b) # a and b both reference same 88 initially
    print(b) # b is not changed
    def changer(a, b): # Arguments assigned references to objects
    a = 2 # Changes local name's value only
    b[0] = 'spam' # Changes shared object in-place
    X = 1
    L = [1, 2] # Caller
    changer(X, L) # Pass immutable and mutable objects
    X, L # X is unchanged, L is different!
    X = 1
    a = X # They share the same object
    a = 2 # Resets 'a' only, 'X' is still 1
    print(X)
    L = [1, 2]
    b = L # They share the same object
    b[0] = 'spam' # In-place change: 'L' sees the change too
    print(L)
  29. 29Avoiding Mutable Argument Changesdef changer(a, b):
    a = 2
    b[0] = 'spam'
    X = 1
    L = [1, 2]
    changer(X, L[:]) # Pass a copy, so our 'L' does not change
    print(X)
    print(L)
    def changer(a, b):
    b = b[:] # Copy input list so we don't impact caller
    a = 2
    b[0] = 'spam' # Changes our list copy only
    L = [1, 2]
    # changer(X, tuple(L)) # Pass a tuple, so changes are errors
  30. 30Simulating Output Parameters and Multiple Resultsdef multiple(x, y):
    x = 2 # Changes local names only
    y = [3, 4]
    return x, y # Return new values in a tuple
    X = 1
    L = [1, 2]
    print('#' * 52 + ' Assign results to caller s names')
    X, L = multiple(X, L) # Assign results to caller's names
    print(X, L)
  31. 31Keywordsdef f(a, b, c): print(a, b, c)
    f(1, 2, 3)
    f(c=3, b=2, a=1)
    f(1, c=3, b=2)
    def func(name='Bob', age=40, job='dev'): print(name, age, job)
    func('Serg,', 40, ', nuker')
  32. 32Defaultsdef f(a, b=2, c=3): print(a, b, c)
    f(1)
    f(a=1)
    f(1, 4)
    f(1, 4, 5)
    f(1, c=6)
  33. 33_combining keywords and defaultsdef func(spam, eggs, toast=0, ham=0): # First 2 required
    print((spam, eggs, toast, ham))
    func(1, 2) # Output: (1, 2, 0, 0)
    func(1, ham=1, eggs=0) # Output: (1, 0, 0, 1)
    func(spam=1, eggs=0) # Output: (1, 0, 0, 0)
    func(toast=1, eggs=2, spam=3) # Output: (3, 2, 1, 0)
    func(1, 2, 3, 4) # Output: (1, 2, 3, 4)
  34. 34Applying functions genericallydef func(a, b, c, d): print(a, b, c, d)
    args = (2,3)
    args += (4,5)
    print(args)
    func(*args)
    def tracer(func, *pargs, **kargs): # Accept arbitrary arguments
    print('calling:', func.__name__)
    return func(*pargs, **kargs) # Pass along arbitrary arguments
    def func(a, b, c, d):
    return(a, b, c, d)
    # def func(a, b, c, d):
    # return a + b + c + d
    print(tracer(func, 1, 2, c=3, d=4))
  35. 35Python 3.X Keyword-Only Argumentsdef kwonly(a, *b, c):
    print(a, b, c)
    kwonly(1, 2, c=3)
    kwonly(a=1, c=3)
    def kwonly(a, *, b, c):
    print(a, b, c)
    kwonly(1, c=3, b=2)
    kwonly(c=3, b=2, a=1)
    def kwonly(a, *, b='spam', c='ham'):
    print(a, b, c)
    kwonly(1)
    kwonly(1, c=3)
    kwonly(a=1)
    kwonly(c=3, b=2, a=1)
    def kwonly(a, *, b, c='spam'):
    print(a, b, c)
    kwonly(1, b='eggs')
    def kwonly(a, *, b=1, c, d=2):
    print(a, b, c, d)
    kwonly(3, c=4)
    kwonly(3, c=4, b=5)
  36. 36Ordering rules Collect args in headerdef f(a, *b, c=6, **d): print(a, b, c, d)
  37. 37Ordering rules Default useddef f(a, *b, c=6, **d)
    f(1, 2, 3, x=4, y=5)
  38. 38Ordering rules Override defaultdef f(a, *b, c=6, **d)
    f(1, 2, 3, x=4, y=5, c=7)
  39. 39Ordering rules Anywhere in keywordsdef f(a, *b, c=6, **d)
    f(1, 2, 3, c=7, x=4, y=5)
  40. 40Ordering rules c is not keyword-onlydef f(a, *b, c=6, **d)
    def f(a, c=6, *b, **d): print(a, b, c, d)
  41. 41Ordering rules KW-only between * and **def f(a, *b, c=6, **d): print(a, b, c, d)
  42. 42Ordering rules Unpack args at calldef f(a, *b, c=6, **d)
    f(1, *(2, 3), **dict(x=4, y=5))
  43. 43Ordering rules Override defaultdef f(a, *b, c=6, **d)
    f(1, *(2, 3), c=7, **dict(x=4, y=5))
  44. 44Ordering rules After or before *def f(a, *b, c=6, **d)
    f(1, c=7, *(2, 3), **dict(x=4, y=5))
  45. 45Ordering rules Keyword-only indef f(a, *b, c=6, **d)
    f(1, *(2, 3), **dict(x=4, y=5, c=7))
  46. 46Recursive Functionsdef mysum(L):
    if not L:
    return 0
    else:
    return L[0] + mysum(L[1:]) # Call myself
    def main():
    print(mysum([1, 2, 3 ,4 ,5]))
  47. 47Recursive Functionsdef mysum(L):
    print(L)
    if not L:
    return 0
    else:
    return L[0] + mysum(L[1:]) # Call myself
    def main():
    print(mysum([1, 2, 3 ,4 ,5]))
  48. 48Recursive Functionsdef mysum(L):
    if not L: return 0
    return nonempty(L) # Call a function that calls me
    def nonempty(L):
    return L[0] + mysum(L[1:]) # Indirectly recursive
    def main():
    print(mysum([1.1, 2.2, 3.3, 4.4]))
  49. 49Indirect Function Calldef echo(message): # Name echo assigned to function object
    print(message)
    echo('Direct call')
    x = echo # Now x references the function too
    x('Indirect call!') # Call object through name by adding ()
    def indirect(func, arg):
    func(arg) # Call the passed-in object by adding ()
    indirect(echo, 'Argument call!') # Pass the function to another function
  50. 50Functions can receive keyword argumentsdef has_keywords(my=True, name='computer'):
    if my:
    print('My', name)
    else:
    print('Not mine', name)
    has_keywords(name='phone')
  51. 51Function can receive unlimited number of positional argumentsdef has_args(*args):
    print('A lot of arguments: ', args)
    has_args(1, 'demo', [1, 2], (9, 'string'))
  52. 52Functions can receive unlimited number of keyword argumentsdef has_kwargs(**kwargs):
    print('A lot of keyword arguments', kwargs)
    print('kwargs is a dict', type(kwargs))
    has_kwargs(any_possible=None, values=[], you_wish=1)
  53. 53Function that will cover 100% of argumentsdef send_anything(*args, **kwargs):
    print('args', args)
    print('kwargs', kwargs)
    send_anything(1, 15, 'a', value=True, new_value=False)
  54. 54Functions can use global variablesGLOBAL_VAR = 3
    def using_global_var(x):
    print(x * GLOBAL_VAR)
    using_global_var(12)
  55. 55Functions can use global variables But if we want to write to it, we should state it explicitlydef writing_to_global_var(value):
    global GLOBAL_VAR
    GLOBAL_VAR = value
    print('it is now', GLOBAL_VAR)
    writing_to_global_var(9)
  56. 56Functions are objects and can be nesteddef outer_function(value):
    def some_inner():
    print('Value was', value)
    return some_inner
    v = outer_function('some')
    print('it is a function', v, callable(v))
    v() # 'some' will be printed
  57. 57mapdef work(value):
    return value * 2
    t = [1, 2, 10]
    m = map(work, t)
    print(m)
  58. 58map but using lambda functionm1 = map(lambda x: x * 2, t)
    print(list(m1))
  59. 59filterprint(list(filter(lambda v: v > 0, [-1, -5, -9, 20, 3, 0])))
  60. 60reducefrom functools import reduce
    r = [1, 4, 2, 3]
    result = reduce(lambda x, y: x + y, r)
    print(result)
  61. 61functions_are_objectsdef my_function():
    print('I am a function')
    print('Functions are objects', isinstance(my_function, object))
  62. 62You can use variables to store functionsdef my_function():
    print('I am a function')
    test = my_function
    test()
  63. 63You can pass functions as parametersdef call_passed_function(incoming):
    print('Calling!')
    incoming()
    print('Called!')
    call_passed_function(my_function)
  64. 64You can check if something could be calledprint(callable(len), callable(45), callable(callable))
  65. 65You can return function from a functiondef return_min_function():
    return min
    test = return_min_function()
    min_value = test(4, 5, -9, 12)
    print('Min values is', min_value)
  66. 66Объявление функции hello_world# Объявление функции hello_world
    def hello_world():
    print('Hello, World!')
    # Вызов функции hello_world
    hello_world()
  67. 67procedure-with-parameter# limit - формальный параметр функции print_numbers
    def print_numbers(limit):
    for i in range(limit):
    print(i)
    # Здесь вызывается функция print_numbers, а её формальный
    # параметр limit замещается фактическим параметром 10
    print_numbers(10)
  68. 68using-builtin-functions# Функция из прошлого примера
    def print_numbers(limit):
    for i in range(limit):
    print(i)
    # Читаем ввод пользователя при помощи стандартной
    # функции input, конструируем из него число при
    # помощи стандартной функции int и записываем в
    # переменную n
    n = int(input('Введите n: '))
    # Вызываем функцию print_numbers с фактическим параметром n
    print_numbers(n)
  69. 69multiple-functions# Функция из прошлого примера
    def print_numbers(limit):
    for i in range(limit):
    print(i)
    # Любое логически завершённое действие следует помещать в функцию
    def main():
    n = int(input('Введите n: '))
    print_numbers(n)
    # Вызов главной функции
    main()
  70. 70main-functiondef main():
    print('Hello, World!')
    # Главную функцию желательно вызывать так
    # (таким образом функция будет вызвана только если
    # данный файл был запущен как главный; это важно
    # для приложений, состоящих из нескольких модулей)
    if __name__ == '__main__':
    main()
  71. 71simple-functiondef add_numbers(a, b):
    return a + b # возврат суммы параметров
    x = add_numbers(2, 3)
    print(x)
  72. 72procedures-as-functionsdef procedure():
    print('I return nothing... Or I do?')
    value = procedure()
    print('Результат функции:', value)
  73. 73multiple-return-statements# Эта функция возвращает аргумент, умноженный на два,
    # если он отрицательный, или аргумент, умноженный на три,
    # если он больше или равен нулю
    def function(x):
    if x < 0:
    return x * 2
    else:
    return x * 3
    def main():
    # Вывод значений функции в диапазоне [-3, 3]
    for i in range(-3, 4):
    y = function(i)
    print('function(', i, ') = ', y, sep='')
    if __name__ == '__main__':
    main()
  74. 74return-in-proceduresdef hello(name):
    # Если имя пустое, выходим из функции
    if not name:
    return
    print('Hello, ', name, '!', sep='')
    hello('Alex')
    hello('')
    hello('Python'
  75. 75functions-in-expressionsdef add(a, b):
    return a + b
    def sub(a, b):
    return a - b
    # Вызов функции может быть частью выражения
    print(add(2, 3) + sub(2, 3)) # => print((2 + 3) + (2 - 3))
  76. 76keyword-arguments# Функция, которая принимает три аргумента
    def info(object, color, price):
    print('Объект:', object)
    print('Цвет:', color)
    print('Цена:', price)
    print()
    # передача параметров в прямом порядке
    info('ручка', 'синий', 1)
    # передача параметров в произвольном порядке
    info(price=5, object='чашка', color='оранжевый')
    # можно смешивать оба способа, но сначала должны идти параметры,
    # которые передаются в прямом порядке
    info('кофе', price=10, color='чёрный')
  77. 77optional-arguments# Если параметр name не задан, то name = 'Alex'
    def hello(name='Alex'):
    print('Hello, ', name, '!', sep='')
    hello('Python')
    hello()
  78. 78functions_as_first_class_objects# Создание ссылки на объект
    out = print
    out('Hello')
    # Сохранение ссылок на функции в структуре данных
    def add(x, y):
    return x + y
    def sub(x, y):
    return x - y
    operations = {
    '+': add,
    '-': sub
    }
    print(operations['+'](2, 3))
    print(operations['-'](2, 3))
  79. 79lambda_expressionsoperations = {
    '+': lambda x, y: x + y,
    '-': lambda x, y: x - y
    }
    print(operations['+'](2, 3))
    print(operations['-'](2, 3))
  80. 80closures"""Пример замыкания"""
    def make_closure():
    variable = 42
    def closure():
    return variable
    return closure
    fn = make_closure()
    print(fn())
  81. 81advanced_closure_example"""Демонстрация часто допускаемой ошибки и способа её решения"""
    def make_powers(n):
    """Функция, возвращающая список функций, каждая из которых вычисляет
    степень аргумента, равную данному индексу плюс 1
    (неправильная реализация)
    """
    functions = []
    for i in range(1, n + 1):
    functions.append(lambda x: x ** i)
    return functions
    for function in make_powers(3):
    print(function(2))
    # Видно, что результататом было не 2, 4, 8, как можно было бы ожидать,
    # а 8, 8, 8
    print()
    # Причиной этого является так называемое позднее связываение. К тому моменту,
    # когда вызываются функции из списка, цикл в функции make_powers уже выполнен и
    # переменная i всегда равна n + 1.
    # Для того, чтобы избавиться от этого, необходимо скопировать данную переменную
    # в локальные переменные каждой функции. Единственный способ создать локальную
    # переменную в лямбда-выражении -- это создать параметр функции.
    def make_powers(n):
    """Функция, возвращающая список функций, каждая из которых вычисляет
    степень аргумента, равную данному индексу плюс 1
    (
  82. 82Пример каррирования функцииdef ordinary_add(x, y):
    """Обычная функция"""
    return x + y
    def curryied_add(x):
    """Каррированная функция"""
    def do_add(y):
    return x + y
    return do_add
    print(ordinary_add(2, 3))
    print(curryied_add(2)(3))
    # Каррирование делает лёгким частичное применение функций
    add_to_five = curryied_add(5)
    print(add_to_five(2))
    print(add_to_five(3))
    print()
    # В виде лямбда-выражений
    ordinary_add = lambda x, y: x + y
    curryied_add = lambda x: lambda y: x + y
    print(ordinary_add(2, 3))
    print(curryied_add(2)(3))
    add_to_five = curryied_add(5)
    print(add_to_five(2))
    print(add_to_five(3))
  83. 83decoratordef decorator(fn):
    """Пример декоратора"""
    def decorated_fn(*args, **kwargs):
    """Модифицированная функция"""
    print('Decorated function says:')
    fn(*args, **kwargs) # вызов изначальной функции
    print()
    return decorated_fn
    @decorator
    def hello():
    print('Hello!')
    # Вызов декорированной функции
    hello()
  84. 84Пример создания декоратора с параметромdef cast_result(type_):
    """Пример создания декоратора с параметром"""
    def cast_decorator(function):
    """Сам декоратор"""
    def decorated_function(*args, **kwargs):
    result = function(*args, **kwargs)
    return type_(result)
    return decorated_function
    return cast_decorator
    @cast_result(float)
    def add(x, y):
    return x + y
    print(add(2, 3))
    import decimal
    @cast_result(repr)
    @cast_result(decimal.Decimal)
    def div(x, y):
    return x / y
    print(div(3, 2))
  85. 85Пример использования функции mapstring = '2 4 8 15 42'
    numbers = map(int, string.split())
    print(list(numbers))
  86. 86Пример использования функции filternumbers = [3, 2, -1, 0, 15, -8, -7, 3, -3, 8]
    positive_numbers = filter(lambda x: x > 0, numbers)
    print(list(positive_numbers))
  87. 87Пример использования функции reducefrom functools import reduce
    numbers = [3, 2, 1, 8, -3, -2]
    # Произведение всех чисел списка
    product = reduce(lambda x, y: x * y, numbers)
    print(product)
  88. 88lru_cachefrom functools import lru_cache
    # Здесь функция вычисления чисел Фибоначчи записана рекурсивно, но по
    # произоводительности и расходу памяти она будет сравнима с нерекурсивной
    @lru_cache(maxsize=None)
    def fibonacci(index):
    if index < 2:
    return 1
    else:
    return fibonacci(index - 1) + fibonacci(index - 2)
    for i in range(1, 1000):
    print(fibonacci(i))
  89. 89partialfrom functools import partial
    # Частичное применение функции
    print_with_comma = partial(print, sep=', ')
    print_with_comma(2, 3, 5)
  90. 90Пример использования комбинаторных генераторов модуля itertoolsfrom itertools import permutations, combinations, combinations_with_replacement
    print(list(permutations('ABC', 2)))
    print()
    print(list(combinations('ABC', 2)))
    print()
    print(list(combinations_with_replacement('ABC', 2)))
  91. 91Пример использования функции product модуля itertoolsfrom itertools import product
    for a, b in product(range(2), range(3)):
    print(a, b)
  92. 92Positional Argumentsdef my_func(a, b, c):
    print("a={0}, b={1}, c={2}".format(a, b, c))
  93. 93Default ValuesNote that once a parameter is assigned a default value, all parameters thereafter must be asigned a default value too!
    def my_func(a, b=2, c=3):
    print("a={0}, b={1}, c={2}".format(a, b, c))
    my_func(10, 20, 30)
    my_func(10, 20)
    my_func(10)
    Since a does not have a default value, it must be specified:
  94. 94Keyword Arguments (named arguments)def my_func(a, b=2, c=3):
    print("a={0}, b={1}, c={2}".format(a, b, c))
    my_func(c=30, b=20, a=10)
    my_func(10, c=30, b=20)
    Note that once a keyword argument has been used, all arguments thereafter must also be named:
    However, if a parameter has a default value, it can be omitted from the argument list, named or not:
    my_func(10, c=30)
    my_func(a=30, c=10)
    my_func(c=10, a=30)
  95. 95arbitrary numbers of positional parameters/arguments:def func1(a, b, *args):
    print(a)
    print(b)
    print(args)
    func1(1, 2, 'a', 'b')
    A few things to note:
    Unlike iterable unpacking, *args will be a tuple, not a list.
    The name of the parameter args can be anything you prefer
    You cannot specify positional arguments after the *args parameter - this does something different that we'll cover in the next lecture.
  96. 96how we might use this to calculate the average of an arbitrary number of parameters.def avg(*args):
    count = len(args)
    total = sum(args)
    return total/count
    avg(2, 2, 4, 4)
    avg() # error
    def avg(*args):
    count = len(args)
    total = sum(args)
    if count == 0:
    return 0
    else:
    return total/count
    avg(2, 2, 4, 4)
    avg()
    But we may not want to allow specifying zero arguments, in which case we can split our parameters into a required (non-defaulted) positional argument, and the rest:
    def avg(a, *args):
    count = len(args) + 1
    total = a + sum(args)
    return total/count
    avg(2, 2, 4, 4)
    avg()
  97. 97Unpacking an iterable into positional argumentsdef func1(a, b, c):
    print(a)
    print(b)
    print(c)
    l = [10, 20, 30]
    The function expects three positional arguments, but we only supplied a single one (albeit a list).
    But we could unpack the list, and then pass it to as the function arguments:
    func1(*l)
  98. 98To make the keyword argument optional, we just need to specify a default value in the function definition:def func1(*args, d='n/a'):
    print(args)
    print(d)
    func1(1, 2, 3)
    func1()
  99. 99Sometimes we want only keyword arguments, in which case we still have to exhaust the positional arguments first - but we can use the following syntax if we do not want any positional parameters passed in:def func1(*, d='hello'):
    print(d)
    func1(10, d='bye')
    func1(d='bye')
  100. 100We can also include positional non-defaulted (first), positional defaulted (after positional non-defaulted) followed lastly (after exhausting positional arguments) by keyword args (defaulted or non-defaulted in any order)def func1(a, b=20, *args, d=0, e='n/a'):
    print(a, b, args, d, e)
    func1(5, 4, 3, 2, 1, d=0, e='all engines running')
    func1(0, 600, d='goooood morning', e='python!')
    func1(11, 'm/s', 24, 'mph', d='unladen', e='swallow')
  101. 101**kwargsdef func(**kwargs):
    print(kwargs)
    func(x=100, y=200)
  102. 102*args **kwargsdef func(*args, **kwargs):
    print(args)
    print(kwargs)
    func(1, 2, a=100, b=200)
  103. 103If you want to specify both specific keyword-only arguments and **kwargs you will need to first get to a point where you can define a keyword-only argument (i.e. exhaust the positional arguments, using either *args or just *)def func(*, d, **kwargs):
    print(d)
    print(kwargs)
    func(d=1, x=100, y=200)
  104. 104Positionals Only: no extra positionals, no defaults (all positionals required)def func(a, b):
    print(a, b)
    func('hello', 'world')
    func(b='world', a='hello')
  105. 105Positionals Only: no extra positionals, defaults (some positionals optional)def func(a, b='world', c=10):
    print(a, b, c)
    func('hello')
    func('hello', c='!')
  106. 106Positionals Only: extra positionals, no defaults (all positionals required)def func(a, b, *args):
    print(a, b, args)
    func(1, 2, 'x', 'y', 'z')
  107. 107Keywords Only: no positionals, no defaults (all keyword args required)def func(*, a, b):
    print(a, b)
    func(a=1, b=2
  108. 108Keywords Only: no positionals, some defaults (not all keyword args required)def func(*, a=1, b):
    print(a, b)
    func(a=10, b=20)
    func(b=2)
  109. 109Keywords and Positionals: some positionals (no defaults), keywords (no defaults)def func(a, b, *, c, d):
    print(a, b, c, d)
    func(1, 2, c=3, d=4)
    func(1, 2, d=4, c=3)
    func(1, c=3, d=4, b=2)
  110. 110Keywords and Positionals: some positional defaultsdef func(a, b=2, *, c, d=4):
    print(a, b, c, d)
    func(1, c=3)
    func(c=3, a=1)
    func(1, 2, c=3, d=4)
    func(c=3, a=1, b=2, d=4)
  111. 111Keywords and Positionals: extra positionalsdef func(a, b=2, *args, c=3, d):
    print(a, b, args, c, d)
    func(1, 2, 'x', 'y', 'z', c=3, d=4)
    Note that if we are going to use the extra arguments, then we cannot actually use a default value for b:
    func(1, 'x', 'y', 'z', c=3, d=4)
  112. 112Keywords and Positionals: no extra positionals, extra keywordsdef func(a, b, *, c, d=4, **kwargs):
    print(a, b, c, d, kwargs)
    func(1, 2, c=3, x=100, y=200, z=300)
    func(x=100, y=200, z=300, c=3, b=2, a=1)
  113. 113Keywords and Positionals: extra positionals, extra keywordsdef func(a, b, *args, c, d=4, **kwargs):
    print(a, b, args, c, d, kwargs)
    func(1, 2, 'x', 'y', 'z', c=3, d=5, x=100, y=200, z=300)
  114. 114Keywords and Positionals: only extra positionals and extra keywordsdef func(*args, **kwargs):
    print(args, kwargs)
    func(1, 2, 3, x=100, y=200, z=300)
  115. 115Another Use Case log_to_consoledef calc_hi_lo_avg(*args, log_to_console=False):
    hi = int(bool(args)) and max(args)
    lo = int(bool(args)) and min(args)
    avg = (hi + lo)/2
    if log_to_console:
    print("high={0}, low={1}, avg={2}".format(hi, lo, avg))
    return avg
    avg = calc_hi_lo_avg(1, 2, 3, 4, 5)
    print(avg)
    avg = calc_hi_lo_avg(1, 2, 3, 4, 5, log_to_console=True)
    print(avg)
  116. 116A Simple Function Timerimport time
    def time_it(fn, *args, rep=5, **kwargs):
    start = time.perf_counter()
    for i in range(rep):
    fn(*args, **kwargs)
    end = time.perf_counter()
    return (end - start) / rep
    def compute_powers_1(n, *, start=1, end):
    # using a for loop
    results = []
    for i in range(start, end):
    results.append(n**i)
    return results
    def compute_powers_2(n, *, start=1, end):
    # using a list comprehension
    return [n**i for i in range(start, end)]
    def compute_powers_3(n, *, start=1, end):
    # using a generator expression
    return (n**i for i in range(start, end))
    compute_powers_1(2, end=5)
    compute_powers_2(2, end=5)
    list(compute_powers_3(2, end=5))
    time_it(compute_powers_1, n=2, end=20000, rep=4)
    time_it(compute_powers_2, 2, end=20000, rep=4)
    time_it(compute_powers_3, 2, end=20000, rep=4)
  117. 117We can define such help using docstringsdef my_func(a, b):
    'Returns the product of a and b'
    return a*b
    help(my_func)
  118. 118Docstrings can span multiple lines using a multi-line string literal:def fact(n):
    '''Calculates n! (factorial function)
    Inputs:
    n: non-negative integer
    Returns:
    the factorial of n
    '''
    if n < 0:
    '''Note that this is not part of the docstring!'''
    return 1
    else:
    return n * fact(n-1)
    help(fact)
    Docstrings, when found, are simply attached to the function in the __doc__ property:
    fact.__doc__
  119. 119Annotationsdef my_func(a:'annotation for a',
    b:'annotation for b')->'annotation for return':
    return a*b
    help(my_func)
  120. 120The annotations can be any expression, not just strings:x = 3
    y = 5
    def my_func(a: str) -> 'a repeated ' + str(max(3, 5)) + ' times':
    return a*max(x, y)
    help(my_func)
  121. 121Just like docstrings are stored in the __doc__ property, annotations are stored in the __annotations__ property - a dictionary whose keys are the parameter names, and values are the annotation.x = 3
    y = 5
    def my_func(a: str) -> 'a repeated ' + str(max(3, 5)) + ' times':
    return a*max(x, y)
    my_func.__annotations__
  122. 122Annotations will work with default parameters too: just specify the default after the annotationdef my_func(a:str='a', b:int=1)->str:
    return a*b
    help(my_func)
    my_func()
    my_func('abc', 3)
    def my_func(a:int=0, *args:'additional args'):
    print(a, args)
    my_func.__annotations__
    help(my_func)
  123. 123Lambda Expressionslambda x: x**2
  124. 124Lambda Assigning to a Variablefunc = lambda x: x**2
    type(func)
    func(3)
  125. 125We can specify arguments for lambdas just like we would for any function created using def, except for annotations:func_1 = lambda x, y=10: (x, y)
    func_1(1, 2)
    func_1(1)
  126. 126Lambda We can even use * and **:func_2 = lambda x, *args, y, **kwargs: (x, *args, y, {**kwargs})
    func_2(1, 'a', 'b', y=100, a=10, b=20)
  127. 127Lambda Passing as an Argument Lambdas are functions, and can therefore be passed to any other function as an argument (or returned from another function)def apply_func(x, fn):
    return fn(x)
    apply_func(3, lambda x: x**2)
    apply_func(3, lambda x: x**3)
  128. 128Lambda Passing as an Argument Lambdas are functions, and can therefore be passed to any other function as an argument (or returned from another function) we can make this even more generic:def apply_func(fn, *args, **kwargs):
    return fn(*args, **kwargs)
    apply_func(lambda x, y: x+y, 1, 2)
    apply_func(lambda x, *, y: x+y, 1, y=2)
    apply_func(lambda *args: sum(args), 1, 2, 3, 4, 5)
  129. 129Lambdas and Sortingl = ['a', 'B', 'c', 'D']
    sorted(l)
    sorted(l, key=str.upper)
    We could have used a lambda here (but you should not, this is just to illustrate using a lambda in this case):
    sorted(l, key = lambda s: s.upper())
  130. 130Lambdas and Sorting Let's look at how we might create a sorted list from a dictionary:d = {'def': 300, 'abc': 200, 'ghi': 100}
    d
    sorted(d)
    sorted(d, key=lambda k: d[k])
  131. 131here's another example where we want to sort a list of strings based on the last character of the string:l = ['Cleese', 'Idle', 'Palin', 'Chapman', 'Gilliam', 'Jones']
    sorted(l)
    sorted(l, key=lambda s: s[-1])
  132. 132Randomizing an Iterable using Sortedimport random
    l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    sorted(l, key=lambda x: random.random())
    sorted('abcdefg', key = lambda x: random.random())
    And to get a string back instead of just a list:
    ''.join(sorted('abcdefg', key = lambda x: random.random()))
  133. 133Function Introspection The name attribute holds the function's name:def my_func(a, b=2, c=3, *, kw1, kw2=2, **kwargs):
    pass
    f = my_func
    my_func.__name__
    f.__name__
  134. 134Function Introspection The defaults attribute is a tuple containing any positional parameter defaults:def my_func(a, b=2, c=3, *, kw1, kw2=2, **kwargs):
    pass
    f = my_func
    my_func.__defaults__
    my_func.__kwdefaults__
  135. 135Function Introspection The code attribute contains a code object:def my_func(a, b=1, *args, **kwargs):
    i = 10
    b = min(i, b)
    return a * b
    my_func('a', 100)
    my_func.__code__
    dir(my_func.__code__)
  136. 136Function Introspection Attribute co_varnames is a tuple containing the parameter names and local variables:def my_func(a, b=2, c=3, *, kw1, kw2=2, **kwargs):
    pass
    f = my_func
    my_func.__code__.co_varnames
  137. 137Function Introspection Attribute co_argcount returns the number of arguments (minus any * and ** args)def my_func(a, b=2, c=3, *, kw1, kw2=2, **kwargs):
    pass
    f = my_func
    my_func.__code__.co_argcount
  138. 138The inspect moduledef my_func(a, b=1, *args, **kwargs):
    i = 10
    b = min(i, b)
    return a * b
    my_func('a', 100)
    import inspect
    inspect.isfunction(my_func)
    inspect.ismethod(my_func)
  139. 139Introspecting Callable Codedef fact(n: "some non-negative integer") -> "n! or 0 if n < 0": """Calculates the factorial of a non-negative integer n
    If n is negative, returns 0.
    """
    if n < 0:
    return 0
    elif n <= 1:
    return 1
    else:
    return n * fact(n-1)
    inspect.getsource(fact)
  140. 140Functions and Methods are callablecallable(print)
    callable(len)
    l = [1, 2, 3]
    callable(l.append)
    s = 'abc'
    callable(s.upper)
  141. 141Callables always return a value:result = print('hello')
    print(result)
    l = [1, 2, 3]
    result = l.append(4)
    print(result)
    print(l)
    s = 'abc'
    result = s.upper()
    print(result)
  142. 142Classes are callable:from decimal import Decimal
    callable(Decimal)
    result = Decimal('10.5')
    print(result)
  143. 143Class instances may be callable:class MyClass:
    def __init__(self):
    print('initializing...')
    self.counter = 0
    def __call__(self, x=1):
    self.counter += x
    print(self.counter)
    my_obj = MyClass()
    callable(my_obj.__init__)
    callable(my_obj.__call__)
    my_obj()
    my_obj()
    my_obj(10)
  144. 144MapThe map built-in function is a higher-order function that applies a function to an iterable type object:
    def fact(n):
    return 1 if n < 2 else n * fact(n-1)
    fact(3)
    fact(4)
    map(fact, [1, 2, 3, 4, 5])
    The map function returns a map object, which is an iterable - we can either convert that to a list or enumerate it:
    l = list(map(fact, [1, 2, 3, 4, 5]))
    print(l)
    We can also use it this way:
    l1 = [1, 2, 3, 4, 5]
    l2 = [10, 20, 30, 40, 50]
    f = lambda x, y: x+y
    m = map(f, l1, l2)
    list(m)
  145. 145FilterThe filter function is a function that filters an iterable based on the truthyness of the elements, or the truthyness of the elements after applying a function to them. Like the map function, the filter function returns an iterable that we can view by generating a list from it, or simply enumerating in a for loop.
    l = [0, 1, 2, 3, 4, 5, 6]
    for e in filter(None, l):
    print(e)
  146. 146is_even with filterdef is_even(n):
    return n % 2 == 0
    l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    result = filter(is_even, l)
    print(list(result))
    Of course, we could just use a lambda expression instead:
    l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    result = filter(lambda x: x % 2 == 0, l)
    print(list(result))
  147. 147Map using a list comprehensionl = [1, 2, 3, 4, 5]
    result = [fact(i) for i in l]
    print(result)
  148. 148The zip built-in function will take one or more iterables, and generate an iterable of tuples where each tuple contains one element from each iterable:l1 = 1, 2, 3
    l2 = 'a', 'b', 'c'
    list(zip(l1, l2))
    l1 = 1, 2, 3
    l2 = [10, 20, 30]
    l3 = ('a', 'b', 'c')
    list(zip(l1, l2, l3))
    l1 = [1, 2, 3]
    l2 = (10, 20, 30)
    l3 = 'abc'
    list(zip(l1, l2, l3))
    l1 = range(100)
    l2 = 'python'
    list(zip(l1, l2))
  149. 149Using the zip function we can now add our two lists element by element as follows:l1 = [1, 2, 3, 4, 5]
    l2 = [10, 20, 30, 40, 50]
    result = [i + j for i,j in zip(l1,l2)]
    print(result)
  150. 150Filtering using a comprehensionl = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    result = [i for i in l if i % 2 == 0]
    print(result)
  151. 151Combining map and filterlist(filter(lambda y: y < 25, map(lambda x: x**2, range(10))))
    Alternatively, we can use a list comprehension to do the same thing:
    x**2 for x in range(10) if x**2 < 25]
  152. 152Suppose we want to find the maximum value in a list: First we define a function that returns the maximum of two arguments:l = [5, 8, 6, 10, 9]
    _max = lambda a, b: a if a > b else b
    def max_sequence(sequence):
    result = sequence[0]
    for x in sequence[1:]:
    result = _max(result, x)
    return result
    max_sequence(l)
  153. 153To calculate the minimum, all we need to do is to change the function that is repeatedly appliedl = [5, 8, 6, 10, 9]
    _min = lambda a, b: a if a < b else b
    def min_sequence(sequence):
    result = sequence[0]
    for x in sequence[1:]:
    result = _min(result, x)
    return result
    print(l)
    print(min_sequence(l))
  154. 154Maximum and Minimum Using Reducing Functionsl = [5, 8, 6, 10, 9]
    _max = lambda a, b: a if a > b else b
    _min = lambda a, b: a if a < b else b
    def _reduce(fn, sequence):
    result = sequence[0]
    for x in sequence[1:]:
    result = fn(result, x)
    return result
    _reduce(_max, l)
    _reduce(_min, l)
    We could even just use a lambda directly in the call to _reduce:
    _reduce(lambda a, b: a if a > b else b, l)
    _reduce(lambda a, b: a if a < b else b, l)
  155. 155Python actually implements a reduce function, which is found in the functools module. Unlike our _reduce function, it can handle any iterable, not just sequences.from functools import reduce
    l = [5, 8, 6, 10, 9]
    l
    reduce(lambda a, b: a if a > b else b, l)
    reduce(lambda a, b: a if a < b else b, l)
    reduce(lambda a, b: a if a < b else b, l)
    reduce(lambda a, b: a + b, l)
  156. 156Finding the max and min of an iterable is such a common thing that Python provides a built-in function to do just that:l = [5, 8, 6, 10, 9]
    max(l), min(l)
    sum(l)
  157. 157The any and all built-insl = [0, 1, 2]
    any(l)
    l = [0, 0, 0]
    any(l)
  158. 158On the other hand, all will return True if every element of the iterable is truthy:l = [0, 1, 2]
    all(l)
    l = [1, 2, 3]
    all(l)
  159. 159We can implement any functions ourselves using reduce if we choose to - simply use the Boolean or or and operators as the function passed to reduce to implement any and all respectively.l = [0, 1, 2]
    reduce(lambda a, b: bool(a or b), l)
    l = [0, 0, 0]
    reduce(lambda a, b: bool(a or b), l)
  160. 160We can implement all functions ourselves using reduce if we choose to - simply use the Boolean or or and operators as the function passed to reduce to implement any and all respectively.l = [0, 1, 2]
    reduce(lambda a, b: bool(a and b), l)
    l = [1, 2, 3]
    reduce(lambda a, b: bool(a and b), l)
  161. 161Partial Functionsfrom functools import partial
    def my_func(a, b, c):
    print(a, b, c)
    f = partial(my_func, 10)
    f(20, 30)
    We could have done this using another function (or a lambda) as well:
    def partial_func(b, c):
    return my_func(10, b, c)
    or, using a lambda:
    fn = lambda b, c: my_func(10, b, c)
    fn(20, 30)
  162. 162Partial Functions it is quite flexible with parameters:def my_func(a, b, *args, k1, k2, **kwargs):
    print(a, b, args, k1, k2, kwargs)
    f = partial(my_func, 10, k1='a')
    f(20, 30, 40, k2='b', k3='c')
    We can of course do the same thing using a regular function too:
    def f(b, *args, k2, **kwargs):
    return my_func(10, b, *args, k1='a', k2=k2, **kwargs)
    f(20, 30, 40, k2='b', k3='c')
  163. 163Partial Functions you are not stuck having to specify the first argument in your partial:def power(base, exponent):
    return base ** exponent
    power(2, 3)
    square = partial(power, exponent=2)
    square(4)
    cube = partial(power, exponent=3)
    cube(2)
    cube(base=3)
  164. 164suppose we have points (represented as tuples), and we want to sort them based on the distance of the point from some other fixed point:origin = (0, 0)
    l = [(1,1), (0, 2), (-3, 2), (0,0), (10, 10)]
    dist2 = lambda x, y: (x[0]-y[0])**2 + (x[1]-y[1])**2
    dist2((0,0), (1,1))
    sorted(l, key = lambda x: dist2((0,0), x))
    sorted(l, key=partial(dist2, (0,0)))
  165. 165we have some generic email() function that can be used to notify someone when various things happen in our application. But depending on what is happening we may want to notify different people.def sendmail(to, subject, body):
    # code to send email
    print('To:{0}, Subject:{1}, Body:{2}'.format(to, subject, body))
    Now, we may haver different email adresses we want to send notifications to, maybe defined in a config file in our app. Here, I'll just use hardcoded variables:
    email_admin = 'palin@python.edu'
    email_devteam = 'idle@python.edu;cleese@python.edu'
    Now when we want to send emails we would have to write things like:
    sendmail(email_admin, 'My App Notification', 'the parrot is dead.')
    sendmail(';'.join((email_admin, email_devteam)), 'My App Notification', 'the ministry is closed until further notice.')
    We could simply our life a little using partials this way:
    send_admin = partial(sendmail, email_admin, 'For you eyes only')
    send_dev = partial(sendmail, email_devteam, 'Dear IT:')
    send_all = partial(sendmail, ';'.join((email_admin, email_devteam)), 'Loyal Subjects')
    send_admin('the parrot is dead.')
    send_all('the ministry is closed until further notice.')
    Finally, let's make this a little more complex, with a mixture of positional and keyword-only argument
  166. 166Functions defined inside anther function can reference variables from that enclosing scope, just like functions can reference variables from the global scope.def outer_func():
    x = 'hello'
    def inner_func():
    print(x)
    inner_func()
    outer_func()
  167. 167if we assign a value to a variable, it is considered part of the local scope, and potentially masks enclsogin scope variable names:def outer():
    x = 'hello'
    def inner():
    x = 'python'
    inner()
    print(x)
    outer()
    As you can see, x** in **outer was not changed.
    To achieve this, we can use the nonlocal keyword:
    def outer():
    x = 'hello'
    def inner():
    nonlocal x
    x = 'python'
    inner()
    print(x)
    outer()
    Of course, this can work at any level as well:
    def outer():
    x = 'hello'
    def inner1():
    def inner2():
    nonlocal x
    x = 'python'
    inner2()
    inner1()
    print(x)
    outer()
  168. 168Let's examine that concept of a cell to create an indirect reference for variables that are in multiple scopes.def outer():
    x = 'python'
    def inner():
    print(x)
    return inner
    fn = outer()
    fn.__code__.co_freevars
    fn.__closure__
  169. 169Modifying the Free Variable We know we can modify nonlocal variables by using the nonlocal keyword. So the following will work:def counter():
    count = 0 # local variable
    def inc():
    nonlocal count # this is the count variable in counter
    count += 1
    return count
    return inc
    c = counter()
    c()
    c()
  170. 170Shared Extended Scopesdef outer():
    count = 0
    def inc1():
    nonlocal count
    count += 1
    return count
    def inc2():
    nonlocal count
    count += 1
    return count
    return inc1, inc2
    fn1, fn2 = outer()
    fn1.__closure__, fn2.__closure__
    As you can see here, the count label points to the same cell.
    fn1()
    fn1()
    fn2()
  171. 171Multiple Instances of Closures Recall that every time a function is called, a new local scope is created.from time import perf_counter
    def func():
    x = perf_counter()
    print(x, id(x))
    func()
    func()
  172. 172Multiple Instances of Closures The same thing happens with closures, they have their own extended scope every time the closure is created:def pow(n):
    # n is local to pow
    def inner(x):
    # x is local to inner
    return x ** n
    return inner
    In this example, n, in the function inner is a free variable, so we have a closure that contains inner and the free variable n
    square = pow(2)
    square(5)
    cube = pow(3)
    cube(5)
    We can see that the cell used for the free variable in both cases is different:
    square.__closure__
    cube.__closure__
  173. 173we wrote a simple closure to count how many times a function had been run:def counter(fn):
    count = 0
    def inner(*args, **kwargs):
    nonlocal count
    count += 1
    print('Function {0} was called {1} times'.format(fn.__name__, count))
    return fn(*args, **kwargs)
    return inner
    def add(a, b=0):
    """
    returns the sum of a and b
    """
    return a + b
    add = counter(add)
    add(1, 2)
    add(2, 2)
  174. 174call that counter function a decorator.def counter(fn):
    count = 0
    def inner(*args, **kwargs):
    nonlocal count
    count += 1
    print('Function {0} was called {1} times'.format(fn.__name__, count))
    return fn(*args, **kwargs)
    return inner
    @counter
    def mult(a: float, b: float=1, c: float=1) -> float:
    """
    returns the product of a, b, and c
    """
    return a * b * c
    mult(1, 2, 3)
    mult(2, 2, 2)
    Let's do a little bit of introspection on our two decorated functions:
    add.__name__
    mult.__name__
  175. 175We can use a special function in the functools module, called wraps. In fact, that function is a decorator itself!from functools import wraps
    def counter(fn):
    count = 0
    @wraps(fn)
    def inner(*args, **kwargs):
    nonlocal count
    count += 1
    print("{0} was called {1} times".format(fn.__name__, count))
    return inner
    @counter
    def add(a: int, b: int=10) -> int:
    """
    returns sum of two integers
    """
    return a + b
    inspect.getsource(add)
    inspect.signature(add)
    inspect.signature(add).parameters
  176. 176Simulating a simple Switch in Pythondef dow_switch_fn(dow):
    if dow == 1:
    fn = lambda: print('Monday')
    elif dow == 2:
    fn = lambda: print('Tuesday')
    elif dow == 3:
    fn = lambda: print('Wednesday')
    elif dow == 4:
    fn = lambda: print('Thursday')
    elif dow == 5:
    fn = lambda: print('Friday')
    elif dow == 6:
    fn = lambda: print('Saturday')
    elif dow == 7:
    fn = lambda: print('Sunday')
    else:
    fn = lambda: print('Invalid day of week')
    return fn()
    dow_switch_fn(1)
    dow_switch_fn(100)
  177. 177Simulating a simple Switch in Python dictionaries could also be used quite effectively here:def dow_switch_dict(dow):
    dow_dict = {
    1: lambda: print('Monday'),
    2: lambda: print('Tuesday'),
    3: lambda: print('Wednesday'),
    4: lambda: print('Thursday'),
    5: lambda: print('Friday'),
    6: lambda: print('Saturday'),
    7: lambda: print('Sunday'),
    'default': lambda: print('Invalid day of week')
    }
    return dow_dict.get(dow, dow_dict['default'])()
    dow_switch_dict(1)
    dow_switch_dict(100)
  178. 178Simulating a simple Switch in Python recall our own implementation of the @singledispatch decorator:def switcher(fn):
    registry = dict()
    registry['default'] = fn
    def register(case):
    def inner(fn):
    registry[case] = fn
    return fn # we do this so we can stack register decorators!
    return inner
    def decorator(case):
    fn = registry.get(case, registry['default'])
    return fn()
    decorator.register = register
    return decorator
    @switcher
    def dow():
    print('Invalid day of week')
    @dow.register(1)
    def dow_1():
    print('Monday')
    dow.register(2)(lambda: print('Tuesday'))
    dow.register(3)(lambda: print('Wednesday'))
    dow.register(4)(lambda: print('Thursday'))
    dow.register(5)(lambda: print('Friday'))
    dow.register(6)(lambda: print('Saturday'))
    dow.register(7)(lambda: print('Sunday'))
    dow(1)
    dow(2)
    dow(100)
  179. 179Introduction to Decorators be_politedef be_polite(fn):
    def wrapper():
    print("What a pleasure to meet you!")
    fn()
    print("Have a great day!")
    return wrapper
    def greet():
    print("My name is Colt.")
    def rage():
    print("I HATE YOU!")
    # we are decorating our function
    # with politeness!
    greet = be_polite(greet)
    polite_rage = be_polite(rage)
    polite_rage()
  180. 180Introduction to Decorators_decorate-syntax - be politedef be_polite(fn):
    def wrapper():
    print("What a pleasure to meet you!")
    fn()
    print("Have a great day!")
    return wrapper
    @be_polite
    def greet():
    print("My name is Colt.")
    @be_polite
    def rage():
    print("I HATE YOU!")
    greet()
    rage()
  181. 181Decorators With Different Signatures shout exampleef shout(fn):
    def wrapper(*args, **kwargs):
    return fn(*args, **kwargs).upper()
    return wrapper
    @shout
    def greet(name):
    return f"Hi, I'm {name}."
    @shout
    def order(main, side):
    return f"Hi, I'd like the {main}, with a side of {side}, please."
    @shout
    def lol():
    return "lol"
    print(greet("todd"))
    print(order(side="burger", main="fries"))
    print(lol())
  182. 182Using Wraps To Preserve Metadatafrom functools import wraps
    def log_function_data(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
    """I AM WRAPPER FUNCTION"""
    print(f"you are about to call {fn.__name__}")
    print(f"Here's the documentation: {fn.__doc__}")
    return fn(*args, **kwargs)
    return wrapper
    @log_function_data
    def add(x, y):
    """Adds two numbers together."""
    return x + y
    print(add.__doc__)
    print(add.__name__)
    help(add)
  183. 183Building A Speed-Test Decoratorfrom functools import wraps
    from time import time
    def speed_test(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
    start_time = time()
    result = fn(*args, **kwargs)
    end_time = time()
    print(f"Executing {fn.__name__}")
    print(f"Time Elapsed: {end_time - start_time}")
    return result
    return wrapper
    @speed_test
    def sum_nums_gen():
    return sum(x for x in range(90000000))
    @speed_test
    def sum_nums_list():
    return sum([x for x in range(90000000)])
    print(sum_nums_gen())
    print(sum_nums_list())
  184. 184Another Example Ensuring Args With A Decoratorfrom functools import wraps
    def ensure_no_kwargs(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
    if kwargs:
    raise ValueError("No kwargs allowed! sorry :(")
    return fn(*args, **kwargs)
    return wrapper
    @ensure_no_kwargs
    def greet(name):
    print(f"hi there {name}")
    greet(name="Tony")
  185. 185290. Writing an ensure_first_arg_is Decorator_ensure-first-argfrom functools import wraps
    def ensure_first_arg_is(val):
    def inner(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
    if args and args[0] != val:
    return f"First arg needs to be {val}"
    return fn(*args, **kwargs)
    return wrapper
    return inner
    @ensure_first_arg_is("burrito")
    def fav_foods(*foods):
    print(foods)
    print(fav_foods("burrito", "ice cream")) # ('burrito', 'ice cream')
    print(fav_foods("ice cream", "burrito")) # 'Invalid! First argument must be burrito'
    @ensure_first_arg_is(10)
    def add_to_ten(num1, num2):
    return num1 + num2
    print(add_to_ten(10, 12)) # 12
    print(add_to_ten(1, 2)) # 'Invalid! First argument must be 10'
  186. 186Enforcing Argument Types With A Decoratordef enforce(*types):
    def decorator(f):
    def new_func(*args, **kwargs):
    # convert args into something mutable
    newargs = []
    for (a, t) in zip(args, types):
    newargs.append( t(a)) # feel free to have more elaborated convertion
    return f(*newargs, **kwargs)
    return new_func
    return decorator
    @enforce(str, int)
    def repeat_msg(msg, times):
    for time in range(times):
    print(msg)
    @enforce(float, float)
    def divide(a, b):
    print(a/b)
    # repeat_msg("hello", '5')
    divide('1', '4')
  187. 187Using a @syntax user_has_permissionuser = {'username': 'jose123', 'access_level': 'guest'}
    def user_has_permission(func):
    def secure_func():
    if user.get('access_level') == 'admin':
    return func()
    return secure_func
    @user_has_permission
    def my_function():
    """
    Allows us to retrieve the password for the admin panel.
    """
    return 'Password for admin panel is 1234.'
    @user_has_permission
    def another():
    pass
    print(my_function.__name__)
    print(another.__name__)
  188. 188Functools wraps in Python user_has_permissionimport functools
    user = {'username': 'jose123', 'access_level': 'guest'}
    def user_has_permission(func):
    @functools.wraps(func)
    def secure_func():
    if user.get('access_level') == 'admin':
    return func()
    return secure_func
    @user_has_permission
    def my_function():
    """
    Allows us to retrieve the password for the admin panel.
    """
    return 'Password for admin panel is 1234.'
    @user_has_permission
    def another():
    pass
    print(my_function.__name__)
    print(another.__name__)
  189. 189Decorating functions with parameters user_has_permissionimport functools
    user = {'username': 'jose123', 'access_level': 'admin'}
    def user_has_permission(func):
    @functools.wraps(func)
    def secure_func(panel):
    if user.get('access_level') == 'admin':
    return func(panel)
    return secure_func
    @user_has_permission
    def my_function(panel):
    """
    Allows us to retrieve the password for the admin panel.
    """
    return f'Password for {panel} panel is 1234.'
    print(my_function.__name__)
    print(my_function('movies'))
  190. 190Decorators with parameters user_has_permissionimport functools
    user = {'username': 'jose123', 'access_level': 'user'}
    def user_has_permission(access_level):
    def my_decorator(func):
    @functools.wraps(func)
    def secure_func(panel):
    if user.get('access_level') == access_level:
    return func(panel)
    return secure_func
    return my_decorator
    @user_has_permission('user')
    def my_function(panel):
    """
    Allows us to retrieve the password for the admin panel.
    """
    return f'Password for {panel} panel is 1234.'
    print(my_function.__name__)
    print(my_function('movies'))
  191. 191Generic decorators for any function user_has_permissionimport functools
    user = {'username': 'jose123', 'access_level': 'admin'}
    def user_has_permission(func):
    @functools.wraps(func)
    def secure_func(*args, **kwargs):
    if user.get('access_level') == 'admin':
    return func(*args, **kwargs)
    return secure_func
    @user_has_permission
    def my_function(panel):
    """
    Allows us to retrieve the password for the admin panel.
    """
    return f'Password for {panel} panel is 1234.'
    @user_has_permission
    def another():
    pass
    print(my_function.__name__)
    print(my_function('movies'))
    print(another())
  192. 192Пример работы с функциями как с объектами первого класса"""Пример работы с функциями как с объектами первого класса"""
    # Создание ссылки на объект
    out = print
    out('Hello')
    # Сохранение ссылок на функции в структуре данных
    def add(x, y):
    return x + y
    def sub(x, y):
    return x - y
    operations = {
    '+': add,
    '-': sub
    }
    print(operations['+'](2, 3))
    print(operations['-'](2, 3))
  193. 193Пример использования лямбда-выраженийoperations = {
    '+': lambda x, y: x + y,
    '-': lambda x, y: x - y
    }
    print(operations['+'](2, 3))
    print(operations['-'](2, 3))
  194. 194Пример замыканияdef make_closure():
    variable = 42
    def closure():
    return variable
    return closure
    fn = make_closure()
    print(fn())
  195. 195Пример использования комбинаторных генераторов модуля itertoolsfrom itertools import permutations, combinations, combinations_with_replacement
    print(list(permutations('ABC', 2)))
    print()
    print(list(combinations('ABC', 2)))
    print()
    print(list(combinations_with_replacement('ABC', 2)))
  196. 196Пример использования функции product модуля itertoolsПример использования функции chain модуля itertools
  197. 197Пример использования функций takewhile и dropwhile модуля itertoolsfrom itertools import takewhile, dropwhile
    numbers = [1, 4, 6, 4, 1]
    predicate = lambda x: x < 5
    for value in takewhile(predicate, numbers):
    print(value)
    print()
    for value in dropwhile(predicate, numbers):
    print(value)
  198. 198Пример использования модуля operatorfrom operator import neg, mul, le
    from functools import reduce, partial
    # Сделать числа списка отрицательными
    print(list(map(neg, [2, 4, 8, 9, 1])))
    # Вычислить произведение элементов списка
    print(reduce(mul, [3, 4, 5]))
    # Оставить только числа, большие или равные пяти (используется оператор <=, так
    # как при помощи функции partial применяется первый аргумент, то есть условие
    # выглядит как 5 <= x).
    print(list(filter(partial(le, 5), [5, 4, 8, 1, 3, 10])))

Informações

Descrição
Advanced Python FlashCards sobre 016_Functions, criado por Serhii Yurskyi em 11-09-2019.
Criado por
Serhii Yurskyi
Visualizações
0
Avaliação

Fale Conosco

Sobre o que é sua mensagem?

O que você acha do novo visual?

Você gostou?