Код выводит (
1, [ ’ х ’ ], { ’ а ’ : ’ у ’ }
) — первое присваивание в функции не оказывает влияния на вызывающий код, но остальные два оказывают, поскольку они модифицируют переданный изменяемый объект на месте.Как прикладывать код задачи: картинкой или текстом?
Anonymous Poll
59%
Картинкой
41%
Текстом (запускаю в интерпретаторе)
Выберите ВЕРНУЮ концепцию о функции из нижеперечисленных:
Anonymous Quiz
7%
Хорошо, когда функция является глубоко вложенной и содержит в себе вызовы других функций.
3%
Следует использовать в функциях как можно больше глобальных переменных.
6%
Хорошо, когда все действия в проекте укладываются в одну функцию.
84%
Каждая функция должна иметь единственное унифицированное значение.
Концепции проектирования функций
Приступив к серьезному использованию функций, вы столкнетесь с необходимостью выбора того, как увязывать компоненты вместе — скажем, каким образом разложить задачу на содержательные функции (известно как сцепление), как функции должны взаимодействовать (называется связностью) и т.д. Вам также придется учитывать такие понятия, как размер функции, поскольку они напрямую влияют на удобство работы с кодом. Некоторые концепции относятся к категории структурного анализа и проектирования, но они применимы к коду на Python как и на любом другом языке.
Ниже приведен обзор нескольких универсальных рекомендаций для читателей, не знакомых с принципами проектирования функций.
• Связность: используйте аргументы для входных данных и оператор return для выходных данных. Как правило, вы должны стремиться сделать функцию независимой от вещей, находящихся за ее пределами. Аргументы и оператор return часто будут наилучшими способами изоляции внешних зависимостей небольшим количеством хорошо известных мест в коде.
• Связность: применяйте глобальные переменные, только когда они по-настоящему нужны. Глобальные переменные (т.е. имена во включающем модуле) обычно являются неудачным способом взаимодействия для функций. Они могут создать
зависимости и проблемы синхронизации, которые затрудняют отладку, изменение и многократное использование программ.
• Связность: не модифицируйте изменяемые аргументы, если только такое изменение не ожидается вызывающим кодом. Функции могут модифицировать части передаваемых изменяемых объектов, но это (как и глобальные переменные)
создает сильную связность между вызывающим и вызываемым кодом, которая может сделать функцию слишком специфичной и хрупкой.
• Сцепление: каждая функция должна иметь единственное унифицированное назначение. При надлежащем проектировании каждая функция должна делать что-то одно — то, что может быть резюмировано в простом повествовательном предложении. Если такое предложение оказывается слишком широким (например, “данная функция реализует всю мою программу”) или содержит много союзов (скажем, “данная функция дает сотруднику повышение и отправляет заказ пиццы”), тогда имеет смысл подумать о разбиении функции на несколько отдельных более простых функций. В противном случае не удастся повторно применять код, который лежит в основе действий, смешанных в функции.
• Размер: каждая функция должна быть относительно небольшой. Цель естественным образом следует из предыдущей цели, но если ваши функции начали занимать несколько страниц на экране редактора, то видимо пришло время их разбить. Прежде всего, учитывая присущую коду Python лаконичность, длинная или глубоко вложенная функция зачастую служит признаком проблем с проектным решением. Сохраняйте функции простыми и короткими.
• Связность: избегайте прямого изменения переменных из другого файла модуля. Тем не менее, для справки помните о том, что изменение переменных через границы файлов приводит к появлению связности между модулями подобно тому, как глобальные переменные связывают функции — модули становятся труднее понимать и многократно использовать. При любой возможности применяйте функции доступа вместо прямых операторов присваивания.
Приступив к серьезному использованию функций, вы столкнетесь с необходимостью выбора того, как увязывать компоненты вместе — скажем, каким образом разложить задачу на содержательные функции (известно как сцепление), как функции должны взаимодействовать (называется связностью) и т.д. Вам также придется учитывать такие понятия, как размер функции, поскольку они напрямую влияют на удобство работы с кодом. Некоторые концепции относятся к категории структурного анализа и проектирования, но они применимы к коду на Python как и на любом другом языке.
Ниже приведен обзор нескольких универсальных рекомендаций для читателей, не знакомых с принципами проектирования функций.
• Связность: используйте аргументы для входных данных и оператор return для выходных данных. Как правило, вы должны стремиться сделать функцию независимой от вещей, находящихся за ее пределами. Аргументы и оператор return часто будут наилучшими способами изоляции внешних зависимостей небольшим количеством хорошо известных мест в коде.
• Связность: применяйте глобальные переменные, только когда они по-настоящему нужны. Глобальные переменные (т.е. имена во включающем модуле) обычно являются неудачным способом взаимодействия для функций. Они могут создать
зависимости и проблемы синхронизации, которые затрудняют отладку, изменение и многократное использование программ.
• Связность: не модифицируйте изменяемые аргументы, если только такое изменение не ожидается вызывающим кодом. Функции могут модифицировать части передаваемых изменяемых объектов, но это (как и глобальные переменные)
создает сильную связность между вызывающим и вызываемым кодом, которая может сделать функцию слишком специфичной и хрупкой.
• Сцепление: каждая функция должна иметь единственное унифицированное назначение. При надлежащем проектировании каждая функция должна делать что-то одно — то, что может быть резюмировано в простом повествовательном предложении. Если такое предложение оказывается слишком широким (например, “данная функция реализует всю мою программу”) или содержит много союзов (скажем, “данная функция дает сотруднику повышение и отправляет заказ пиццы”), тогда имеет смысл подумать о разбиении функции на несколько отдельных более простых функций. В противном случае не удастся повторно применять код, который лежит в основе действий, смешанных в функции.
• Размер: каждая функция должна быть относительно небольшой. Цель естественным образом следует из предыдущей цели, но если ваши функции начали занимать несколько страниц на экране редактора, то видимо пришло время их разбить. Прежде всего, учитывая присущую коду Python лаконичность, длинная или глубоко вложенная функция зачастую служит признаком проблем с проектным решением. Сохраняйте функции простыми и короткими.
• Связность: избегайте прямого изменения переменных из другого файла модуля. Тем не менее, для справки помните о том, что изменение переменных через границы файлов приводит к появлению связности между модулями подобно тому, как глобальные переменные связывают функции — модули становятся труднее понимать и многократно использовать. При любой возможности применяйте функции доступа вместо прямых операторов присваивания.
🔥1
Какие из способов вызова функции echo() рабочие?
Anonymous Quiz
9%
Только 1
42%
Только 2
39%
Оба
10%
Никакой не сработает
х = echo # Теперь x тоже ссылается на объект функции
х('Indirect call!') # Вызов объекта через имя х путем добавления ()
Поскольку аргументы передаются по присваиванию объектов, функции легко передавать другим функциям в качестве аргументов. Вызываемая функция затем может
вызвать переданную функцию, просто добавив аргументы в круглых скобках:
def indirect(func, arg) :
func(arg) # Вызов переданного объекта путем добавления ()
indirect (echo, 'Argument call!') # Передача функции другой функции
Объекты функций можно даже помещать внутрь структур данных, как если бы они были целыми числами или строками. Например, в следующем коде функция дважды встраивается в список кортежей, который исполняет роль таблицы действий. Из-за того, что составные типы Python подобного рода способны содержать объекты любых видов, здесь также нет какого-то особого случая:
>>> schedule = [(echo, 'Spam!'), (echo, 'Ham?')]
>>> for (func, arg) in schedule:
>>> func(arg) # Вызов функций, встроенных в контейнер
... Spam!
... Ham!
В коде просто производится проход по списку
schedule
и вызов функции echo
с одним аргументом на каждой итерации (обратите внимание в заголовке цикла for на распаковывающее присваивание кортежа, представленное в главе 13). Функции также можно создавать и возвращать для применения где-то в другом месте — замыкания, созданные в таком режиме, еще и предохраняют состояние из объемлющей области видимости.Код возвращает 6 из-за того, что функция
1. Функция
-
-
-
-
2. Сложение аргументов:
Когда вы вызываете
-
-
-
func
складывает три аргумента: a
, b
и c
. Давайте разберем, что происходит в коде более подробно.1. Функция
func
: def func(a: 'spam', b: (1, 10), c: float) -> int:
-
a: 'spam'
: Это аннотация для параметра a
. Текст 'spam'
здесь не имеет особого значения в самом коде, скорее всего, это просто строка, которая может использоваться для документации или информации о том, какой тип ожидался. В действительности, это просто строка, и Python не проводит никаких проверок типов на основе этой аннотации.-
b: (1, 10)
: Это также аннотация, которая указывает, что b
должен быть значением, соответствующим кортежу (1, 10)
. Однако, как и в случае с аннотацией для a
, эта информация не проверяется в самом коде.-
c: float
: Это аннотация, указывающая, что параметр c
должен быть типа float
.-
-> int
: Это аннотация, которая указывает, что функция будет возвращать значение типа int
.2. Сложение аргументов:
Когда вы вызываете
func(1,2,3)
, переданная строка 1
, 2
и 3
становятся значениями a
, b
и c
соответственно. То есть:-
a = 1
-
b = 2
-
c = 3
>>> func.__annotations__
... {'с': class 'float’>, ’b’: (1, 10), 'a': 'spam', 'return': <class ’int’>}
Какое способ задать тип выводимого foo() значения является самым эффективным с точки зрения интерпретатора?
Anonymous Quiz
35%
1
32%
2
12%
3
21%
Все одинаковы
Вы можете использовать стандартные значения для аргументов в случае снабжения их аннотациями — аннотация (и ее символ
:
) появляется перед стандартным значением (и символом =
). В показанном ниже коде а: 'spam' = 4
означает, что аргумент а имеет стандартное значение 4 и аннотирован строкой 'spam'
:>>> def func(a: 'spam' = 4, b: (1, 10) = 5, c: float = 6) -> int:
>>> return a + b + c
>>> func (1, 2, 3)
... 6
>>> func() # 4 + 5 + 6 (все стандартные значения)
... 15
>>> func(1, с=10) # 1+5 + 10 (ключевые аргументы нормально работают)
... 16
>>> func.__annotations__
{'с': <class 'float;>, 'b': (1, 10), 'a': 'spam', 'return': class 'int'>}
Общая форма лямбда-функций выглядит как ключевое слово
Как и в случае
lambda
, за которым следует один или больше аргументов (очень похоже на список аргументов, заключенный в круглые скобки в заголовке def
) и далее выражение после двоеточия:lambda аргумент!, аргумент2, . . . аргументы : выражение , использующее аргументы
Как и в случае
def
, для аргументов lambda
можно указывать стандартные значения:x = (lambda a="fee", b="fie", c="foe": a + b + c)
print(x("wee")) # weefiefoe