>>> list=[None]
>>> def list[0](x,y):
File "<stdin>", line 1
def list[0](x,y):
^
SyntaxError: invalid syntax
Как определить функцию как элемент списка?Определить функцию как элемент списка
Синтаксис определения>>> list=[None]
>>> def list[0](x,y):
File "<stdin>", line 1
def list[0](x,y):
^
SyntaxError: invalid syntax
Как определить функцию как элемент списка?Определить функцию как элемент списка
Синтаксис определенияPython's def
не является достаточно гибким, чтобы обрабатывать общий lvalues, такой как list[0]
. Язык только позволяет вам использовать идентификатор в качестве имени функции. Вот соответствующие части grammar rule for the def-statement:
funcdef ::= "def" funcname "(" [parameter_list] ")" ":" suite
funcname ::= identifier
Вместо этого, вы можете использовать ряд операторов присваивания и определения:
s = [None]
def f(x, y):
return x + y
s[0] = f
В качестве альтернативы можно также хранить lambda
expression непосредственно в списке :
s = [lambda x,y : x+y]
def f(whatever):
do_stuff()
l[0] = f
Функция не позволяет определить функцию непосредственно в структуру данных, но вы можете просто создать функцию, а затем назначить его туда, куда ему нужно идти.
Или 'l = []; l.append (f) ' – SethMMorton
@SethMMorton: Или просто' l = [f] ', если вы контролируете создание' l' вместо того, чтобы пытаться назначить функцию в существующее место, но я решил, что это будет более ясным , – user2357112
def someFunctionA(x, y):
return x+y
def someFunctionB(x, y):
return x*y
someList = [someFunctionA, someFunctionB]
print someList[0](2, 3)
print someList[1](5, 5)
Почему бы не 'l = [someFunctionA, someFunctionB]'? (Кроме того, лучше не использовать 'list' в качестве идентификатора.) – glglgl
Я сделал это первым, но получил ошибку и подумал, что необходима лямбда. Сейчас это работает, но очевидно, что лямбда была излишней. +1! – Akinakes
Я думаю, что жалоба на использование 'list' в качестве идентификатора стоит. Тень «список» не очень хорош. – tacaswell
Учитывая такое свобода будет делать синтаксический разбор сложнее ... например, выражение в скобках
...(x, y, z=3)
может быть либо декларация параметра (где 3
по умолчанию для параметра ключевого слова г) или вызова (который проходит значение параметра z
ключевого слова в качестве 3
).
Если вы хотите разрешить общий назначаемой выражение в def
вы также должны позволить
def foo(x, y, z=3)[3](x, y, z=3):
...
, где первая часть имеет в скобках различное смысловое значение и синтаксические правила из второй части.
Написание парсера для этого является раздражающим (в основном потому, что вам нужно обработать произвольное неограниченное количество исходного кода, не понимая его), и это то, что, например, приводит к худшему правилу синтаксического анализа во всей вселенной, которую я знаю (это страшный most vexing parse C++), которые в основном просто отказались от попыток получить достойный язык, отказавшись от двусмысленности.
Обратите внимание, что во многих случаях, когда программе сложнее выполнять синтаксический анализ, из-за двусмысленности, которая также затрудняет понимание человеком этого человека.
Python правильно оценивает читаемость как очень важную.
Функция в Python, однако первые объекты класса, так что вы можете решить вашу проблему достаточно легко:
def foo(...):
...
mylist[index] = foo
или, только если функция является одиночным выражением
mylist[index] = lambda ... : ...
(но lambda
очень ограничен, потому что это своего рода «ненавистный» в сообществе Python, а также потому, что он создаст некоторое раздражение на уровне синтаксиса из-за необходимости обработки отступов внутри скобок).
Обратите также внимание на то, что некоторые новички Python не знают, что вы можете использовать def
даже внутри функции; например:
def register_http():
def handle_http(connection):
...
global_register['http'] = handle_http
, который будет назначить функцию в качестве элемента глобальной карты без загрязнения глобальных (модуль) имен с его именем. Локальный def
также может создавать замыкание путем захвата локальных переменных состояния (только для чтения в 2.x или даже чтения/записи в 3.x).
Обратите также внимание, что если вам нужна некоторая обработка функции, может быть decorators
может быть полезна. Например, путем определения
def register(name):
def do_registering(f):
global_register[name] = f
return f
return do_registering
вы можете просто использовать
@register('http')
def handle_http(connection):
...
Вы совершенно правы, но, увы, я должен рассказать о том, что такая сложная вещь нужна. Существует очень хороший синтаксический элемент: декораторы. Они могли легко использовать для этого. То, что я иногда делаю, это вернуть или дать функцию, но декораторы не работают для операторов. Однако '@ return' или' @ yield' было бы неплохо. В этом случае мы могли бы иметь «@ = target» (было бы уродливо из-за назначения назначения справа) или, возможно, '@@ target', например' @@ global_register ['http'] 'перед функция, устраняя необходимость в уродливой строке назначения/выхода/возврата после функции. – glglgl
@glglgl: вы можете сделать что-то более простое, чем при использовании параметрических декораторов типа '@register ('http')'. Они вроде странны для реализации (параметрический декоратор должен вернуть непараметрическую функцию декоратора), но они приятны в использовании. См. Править. – 6502
Правильно, это хорошая альтернатива в этом случае; Я забыл об этом. Но, увы, нельзя использовать для упрощения таких вещей, как 'yield' или' return'. – glglgl
Что вы пытаетесь сделать? Я думаю, что вы хотите не то, что вы не должны делать, но даже тогда я не уверен, что вы спрашиваете. – TerryA
Я очень впечатлен, почему так много пользователей используют этот законный вопрос. – Hyperboreus
Это совершенно законный вопрос. Некоторые другие языки допускают общие значения (а не только идентификаторы) как цель определения функции. ОП разумно полагал, что Python может поддерживать подобную гибкость в задачах определения функций. –