Дополнительные возможности в определении функций
В языке Python можно определить функцию с переменным числом аргументов. Для этого существуют три способа, которые можно комбинировать.
🕛 11.07.2009, 13:16
Значения аргументов по умолчаниюНаиболее полезный способ - установить значения по умолчанию для одного или нескольких аргументов. Таким образом, получается функция, которую можно вызывать с меньшим количеством аргументов, чем в определении, например:
def ask_ok(prompt, retries=4, complaint='Да или нет, пожалуйста!'): while 1: ok = raw_input(prompt) if ok in ('д', 'да'): return 1 if ok in ('н', 'не', 'нет'): return 0 retries = retries - 1 if retries < 0: raise IOError( 'Пользователь отказывается отвечать') print complaint
Эта функция может быть вызвана так: 'ask_ok('Вы действительно хотите выйти?')', или так: 'ask_ok('Перезаписать файл?', 2)'.
Значения по умолчанию вычисляются в месте определения функции в области видимости определения, так что
i = 5
def f(arg = i): print arg
i = 6
f()
выведет 5.
Важное замечание: значение по умолчанию вычисляется только один раз. Это отражается в том случае, когда аргумент со значением по умолчанию является объектом, допускающим изменения, таким как список или словарь. Например, следующая функция накапливает передаваемые аргументы (то есть переменная l является статической) [Такое поведение является, скорее, нежелательной особенностью языка, использование которой может привести к трудно отлавливаемым ошибкам. В качестве статических переменных рекомендуется использовать глобальные переменные модуля.]:
def f(a, l = []): l.append(a) return l
print f(1)
print f(2)
print f(3)
Результат выполнения будет следующий:
[1]
[1, 2]
[1, 2, 3]
Если Вы не хотите, чтобы аргумент по умолчанию совместно использовался при последующих вызовах, можете немного изменить функцию:
def f(a, l = None): if l is None: l = [] l.append(a) return l
Произвольный набор аргументов
Наконец, не так часто используемый вариант - определить функцию таким образом, чтобы ее можно было вызвать с произвольным числом аргументов. В этом случае аргументы будут переданы в виде кортежа (Кортеж - своего рода последовательность объектов, в которую Вы не можете вносить изменения.). Перед переменным числом аргументов может присутствовать произвольное число обычных аргументов:
def fprintf(file, format, *args): file.write(format % args)
Именованные аргументы
Функция может быть вызвана с использованием именованных аргументов (keyword arguments) в виде 'keyword = value'. Например, функция ask_ok() (раздел 4.7.1) может быть вызвана следующими способами:
ask_ok('Вы действительно хотите выйти?')
ask_ok(retries = 2, prompt = 'Перезаписать файл?')
ask_ok('Продолжим?', complaint = 'А теперь то же самое, только по-русски!')
ask_ok('Удалить все файлы из корневого раздела?', 100, 'А может все-таки удалить?')
Однако следующие вызовы ошибочны:
# отсутствует обязательный аргумент
ask_ok()
# неименованный аргумент следует за именованным
ask_ok(prompt = 'Перезаписать файл?', 2)
# два значения для одного аргумента
ask_ok('Продолжим?', prompt = 'Да/нет')
# неизвестное имя аргумента
ask_ok(actor = 'Никулин')
В общем, в списке аргументов именованные аргументы должны следовать после позиционных. Не имеет значения, имеет неименованный аргумент значение по умолчанию или нет. Никакой аргумент не может быть передан более одного раза:
>>> def function(a):
... pass
...
>>> function(0, a=0)
Traceback (innermost last): File "<stdin>", line 1, in ?
TypeError: keyword parameter redefined
Если в определении функции присутствует формальный параметр в виде **name, то его значением становится словарь, содержащий все именованные аргументы, чьи имена не соответствуют формальным параметрам. Такой способ можно комбинировать с формой *name, позволяющей получить кортеж (tuple), содержащий позиционные аргументы, не входящие в список формальных параметров. (Запись **name должна следовать после записи *name.) Например, определим функцию:
def example(formal, *arguments, **keywords): print "Количество пользователей:", formal print '-'*40 for arg in arguments: print arg print '-'*40 for kw in keywords.keys(): print kw, ':', keywords[kw]
Ее можно вызвать следующим образом:
example(1000000, 'Это очень много', 'Это действительно очень много', language = 'Python', author = 'Guido van Rossum')
Вывод будет таким:
Количество пользователей: 1000000
-Это очень много
Это действительно очень много
-language: Python
author: Guido van Rossum
Короткая форма
Python содержит несколько популярных особенностей, характерных для языков функционального программирования. С помощью ключевого слова lambda Вы можете создать простую функцию без имени. Например, функция, возвращающая сумму двух своих аргументов, может быть записана как 'lambda a, b: a+b'. Короткая форма может быть использована везде, где требуется объект-функция. Ее синтаксис ограничен одним выражением. Как и в обычных определениях функций, при записи в короткой форме Вы не можете ссылаться на переменные, находящиеся в области видимости, которая содержит определение этой функции. Однако это ограничение можно обойти, используя значения аргументов по умолчанию:
>>> def make_incrementor(n):
... return lambda x, incr=n: x+incr
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43
Строки документации
Строки документации обычно состоят из одной строки с кратким изложением назначения (или использования) объекта и более подробного описания, разделенных пустой строкой. Первая строка часто используется интегрированными средами разработки (например, IDLE) в качестве подсказки при использовании объекта. Большинство встроенных объектов и объектов, определенных в стандартной библиотеке, снабжены строками документации - используйте их в качестве примеров оформления. Например:
>>> print map._doc_
map(function, sequence[, sequence, ...]) -> list
Return a list of the results of applying the function
to the items of the argument sequence(s). If more than
one sequence is given, the function is called with an
argument list consisting of the corresponding item of
each sequence, substituting None for missing values
when not all sequences have the same length. If the
function is None, return a list of the items of the
sequence (or a list of tuples if more than one
sequence).
Интерпретатор языка Python не убирает отступы в многострочных строковых литеральных выражениях. Поэтому средства, обрабатывающие строки документации, должны это делать сами. Для определения уровня отступа всей строки документации используется первая непустая строка после первой строки (первая строка обычно записывается без отступа). Именно на столько следует уменьшить уровень отступа всей документации при выводе.
Вызов функций
Помимо описанного (func(arg ... )), язык Python предоставляет еще несколько способов вызова функций. Начиная с версии 1.6, Вы можете указать кортеж позиционных и словарь именованных аргументов, например:
args = ('Это очень много', 'Это действительно очень много')
kwds = {'language': 'Python', 'author': ?Guido van Rossum?)
example(1000000, *args, **kwds)
Такой же эффект можно получить используя встроенную функцию apply():
apply(example, (1000000,)+args, kwds)
С помощью средств функционального программирования Вы можете применить функцию к элементам последовательности