Расширенные возможности функций
• Взаимодействие: для передачи значений функции используйте аргументы, для возврата результатов – инструкцию return.
• Взаимодействие: используйте глобальные переменные, только если это
действительно необходимо.
• Взаимодействие: не воздействуйте на изменяемые аргументы, если вызывающая программа не предполагает этого.
• Связность: каждая функция должна иметь единственное назначение.
• Размер: каждая функция должна иметь относительно небольшой размер.
Немного о классах в Python ООП:
Так как язык Python объектно ориентированный (ООП), а ООП часто зависит от функций и классов, тогда стоит рассмотреть одну из возможностей класса.
Классы в языке Python зависят от изменения передаваемого изменяемого объекта – функции воздействуют на атрибуты аргумента self, получаемого автоматически, изменяя информацию о его состоянии (например, self.name = ‘bob’). Кроме того, когда нет возможности использовать классы, часто наилучший способ сохранения информации о состоянии между вызовами функций представляют глобальные переменные в модуле.
Язык Python поддерживает рекурсивные функции – функции, которые могут вызывать сами себя, прямо или косвенно, образуя цикл.
Вычисляем сумму с применением рекурсии:
>>> def mysum(L):
... if not L:
... return 0
... else:
... return L[0] + mysum(L[1:]) # Вызывает себя саму
>>> mysum([1, 2, 3, 4, 5])
15
Альтернативные решения:
def mysum(L):
return 0 if not L else L[0] + mysum(L[1:]) # Трехместный оператор
def mysum(L): # Суммирует любые типы
return L[0] if len(L) == 1 else L[0] + mysum(L[1:])
#предполагает наличие хотя бы одного значения
def mysum(L):
first, *rest = L
return first if not rest else first + mysum(rest)
# Использует расширенную операцию присваивания
# последовательностей
Результаты:
>>> mysum([1]) # mysum([]) будет завершаться ошибкой в 2 последних функциях
1
>>> mysum([1, 2, 3, 4, 5])
15
>>> mysum((‘s’, ‘p’, ‘a’, ‘m’)) # Но они могут суммировать данные любых типов
‘spam’
>>> mysum([‘spam’, ‘ham’, ‘eggs’])
‘spamhameggs’
-----------------------------------------------------------------
Обработка структур данных:
Рекурсия является мощным инструментом для работы с различными структурами данных. Далее мы рассмотрим пример для нахождение суммы всех чисел определенной структуры, которая состоит из вложенных списков.
Пример:
[1, [2, [3, 4], 5], 6, [7, 8]] # Произвольно вложенные списки
def sumtree(L):
tot = 0
for x in L: # Обход элементов одного уровня
if not isinstance(x, list):
tot += x # Числа суммируются непосредственно
else:
tot += sumtree(x) # Списки обрабатываются рекурсивными
return tot #вызовами
L = [1, [2, [3, 4], 5], 6, [7, 8]] # Произвольная глубина
# вложения
print(sumtree(L)) # Выведет 36
# Патологические случаи
print(sumtree([1, [2, [3, [4, [5]]]]])) # Выведет 15 (центр тяжести справа)
print(sumtree([[[[[1], 2], 3], 4], 5])) # Выведет 15 (центр тяжести слева)
Функции в языке Python гораздо более гибкие. Функции в языке Python являются полноценными объектами, хранящими в памяти все, чем они владеют. Кроме того, они свободно могут передаваться между частями программы и вызываться косвенно. У них также есть некоторые особенности, которые имеют мало общего с вызовами, – атрибуты и аннотации.
Косвенный вызов функций:
В имени, которое используется в инструкции def, нет ничего уникального: это всего лишь переменная, которая создается в текущей области видимости, как если бы оно стояло слева от знака =. После того как инструкция def будет выполнена, имя функции представляет собой всего лишь ссылку на объект – ее можно присвоить другим именам и вызывать функцию по любому из них (не только по первоначальному имени):
>>> def echo(message): # Имени echo присваивается объект функции
... print(message)
...
>>> echo(‘Direct call’)
Direct call
>>> x = echo
>>> x(‘Indirect call!’)
Indirect call
-----------------------------------------------------------------
Функции легко можно передавать другим функциям в виде аргументов:
>>> def indirect(func, arg):
... func(arg) # Вызов объекта добавлением ()
...
>>> indirect(echo, ‘Argument call!’) # Передача функции в функцию
Argument call!
-----------------------------------------------------------------
Также возможно наполнять структуры данных функциями, как если бы они были простыми числами или строками. В этом нет ничего необычного, так как составные типы объектов могут содержать объекты любых типов:
>>> schedule = [ (echo, ‘Spam!’), (echo, ‘Ham!’) ]
>>> for (func, arg) in schedule:
... func(arg) # Вызов функции, сохраненной в контейнере
...
Spam!
Ham!
Выполняется обход списка schedule и производится вызов функции echo с одним аргументом.
-----------------------------------------------------------------
Завершающий простой пример:
>>> def make(label): # Создает функцию, но не вызывает ее
... def echo(message):
... print(label + ‘:’ + message)
... return echo
...
>>> F = make(‘Spam’) # Метка сохраняется во вложенной области видимости
>>> F(‘Ham!’)
# Вызов функции, созданной функцией make
Spam:Ham!
>>> F(‘Eggs!’)
Spam:Eggs!
-----------------------------------------------------------------
Комментариев нет:
Отправить комментарий