и хочу еще обратить внимание на то, что lambda (x, y): expr и lambda x, y: expr — две разных ф-ции. Первая принимает один параметр, который должен мочь распаковаться (т.е. быть iterable) в ровно два элемента, тогда как вторая функция принимает два аргумента. Пример использования первой:
t = (a, b) # либо [a, b], iter([a, b]) и т.д.
print (lambda (x, y): x + y)(t)
или короче print (lambda (x, y): x + y)((a, b)) (скобки не лишние).
Вторая используется, соответственно, print (lambda x, y: x + y)(a, b).
И, естественно, с помощью лямбд можно делать замыкания (closures), рекурсию и все другие прикольные вещи, которые можно сделать, используя именованную форму записи функции.
Лямбда без аргументов делается просто: print lambda: 10 - 3. :) По вкусу можно написать print (lambda: 10 - 3), чтобы избежать неоднозначностей при возврате tuple-ов.
Хочу только заметить, что лямбда функция и обычная функция (через def) суть есть одно и то же, они ничем не отличаются даже в мелочах. В лямбдах можно точно так же задавать keyword- и расширенные аргументы и делать аргументы по умолчанию.
Ну вот эта лямбда-функция, как и любая другая функция, при запросе символа, которого нет в локальном пространстве имен, будет смотреть в более верхней(-ем?) «scope» — области видимости (технически — сначала в sys._getframe().f_locals, затем в f_globals и f_builtin) и так пока не найдет нужный символ, либо «наступит» NameError.
Поэтому значение parse станет известно непосредственно при вызове этой функции. Можно вообще написать нечто вида def abc(): return this_name_will_never_exist + 1 и оно нормально скомпилируется и даже запустится, правда, вывалив NameError.
Почти :) Вот как выглядит пример полного синтаксиса — def foo(a, b, c, d = 1, e = None, f = '3', *args, **kwarg). Порядок важен — сначала позиционные аргументы, затем keyword-аргументы, только затем *args и **kwarg. args и kwarg — просто общепринятые названия, и могут быть любыми по вкусу :)
Ну хорошо, давайте рассмотрим ваш пример на C++. Я перевел его в эквивалентный исходный код на Python (он немного «грязен» из-за «некрасивости» примера):
class A:
a = 0
def inc(self):
A.a += 1
return A.a
При вызове inc() в любом экземпляре класса A значение a (т. н. class attribute в терминологии Python) изменится сразу во всех экземплярах класса. Программист волен пользоваться и instance attribute — при этом аттрибут будет персональным для каждого экземпляра класса. Собственно, лично я не вижу никакой путаницы :) При многопоточном программировании надо будет всего лишь обернуть inc в lock-и.
Ну почему не известно? Во-первых, мы не инициализируем объект в нашем случае, а объявляем функцию (да, я знаю, что функция — тоже объект, но сейчас это не играет роли). Во вторых, даже если бы это был объект, что тут странного? Рассмотрим поближе:
def some_func():
return 'Hello!'
def some_func2():
return [1, 2, 3]
def my_func(a = some_func(), b = some_func2()):
print a, b
my_func()
Этот код выведет, соответственно, Hello! [1, 2, 3]. Почему? Потому что все функции были выполнены на момент объявления функции. Естественно, если попытаться из some_func-ов потрогать my_func, нам просто скажут, что нет такого объекта. И правильно сделают — сначала объект создается, а лишь потом ему назначается референс в виде идентификатора.
Какбэ несколько другая ситуация, если мы захотим из my_func-а поизменять b — в данном случае, мы будем всегда работать с одним и тем же списком, потому что его значение уже было однажды вычислено, а списки являются mutable объектами (т.е. могут менять своё содержимое), тогда как строка 'Hello!' — immutable, т.е. значение своё менять не может и после каждой операции со строками создается новый экземпляр.
Ффух. Вот. Надеюсь, я всё это не зря писал и к концу текста понятно, что я хотел сказать в начале :)
Вот как раз в тех патчах, о которых Вы говорите, реклама пряталась, но её загрузка всё равно выполнялась, потому что автор патчей орудовал редакторами ресурсов, а никак не дизассемблером.
t
из первого примера, то так:print (lambda x, y: x + y)(*t)
.Надеюсь, я всех окончательно запутал :)
lambda (x, y): expr
иlambda x, y: expr
— две разных ф-ции. Первая принимает один параметр, который должен мочь распаковаться (т.е. быть iterable) в ровно два элемента, тогда как вторая функция принимает два аргумента. Пример использования первой:или короче
print (lambda (x, y): x + y)((a, b))
(скобки не лишние).Вторая используется, соответственно,
print (lambda x, y: x + y)(a, b)
.print lambda: 10 - 3
. :) По вкусу можно написатьprint (lambda: 10 - 3)
, чтобы избежать неоднозначностей при возврате tuple-ов.Хочу только заметить, что лямбда функция и обычная функция (через def) суть есть одно и то же, они ничем не отличаются даже в мелочах. В лямбдах можно точно так же задавать keyword- и расширенные аргументы и делать аргументы по умолчанию.
varargslist: ((fpdef ['=' test] ',')*
('*' NAME [',' '**' NAME] | '**' NAME) |
fpdef ['=' test] (',' fpdef ['=' test])* [','])
sys._getframe().f_locals
, затем вf_globals
иf_builtin
) и так пока не найдет нужный символ, либо «наступит»NameError
.Поэтому значение
parse
станет известно непосредственно при вызове этой функции. Можно вообще написать нечто видаdef abc(): return this_name_will_never_exist + 1
и оно нормально скомпилируется и даже запустится, правда, вываливNameError
.def foo(a, b, c, d = 1, e = None, f = '3', *args, **kwarg)
. Порядок важен — сначала позиционные аргументы, затем keyword-аргументы, только затем*args
и**kwarg
.args
иkwarg
— просто общепринятые названия, и могут быть любыми по вкусу :)При вызове
inc()
в любом экземпляре классаA
значениеa
(т. н. class attribute в терминологии Python) изменится сразу во всех экземплярах класса. Программист волен пользоваться и instance attribute — при этом аттрибут будет персональным для каждого экземпляра класса. Собственно, лично я не вижу никакой путаницы :) При многопоточном программировании надо будет всего лишь обернуть inc в lock-и.Этот код выведет, соответственно,
Hello! [1, 2, 3]
. Почему? Потому что все функции были выполнены на момент объявления функции. Естественно, если попытаться из some_func-ов потрогать my_func, нам просто скажут, что нет такого объекта. И правильно сделают — сначала объект создается, а лишь потом ему назначается референс в виде идентификатора.Какбэ несколько другая ситуация, если мы захотим из
my_func
-а поизменятьb
— в данном случае, мы будем всегда работать с одним и тем же списком, потому что его значение уже было однажды вычислено, а списки являются mutable объектами (т.е. могут менять своё содержимое), тогда как строка 'Hello!' — immutable, т.е. значение своё менять не может и после каждой операции со строками создается новый экземпляр.Ффух. Вот. Надеюсь, я всё это не зря писал и к концу текста понятно, что я хотел сказать в начале :)
/etc/shadow
под серьезным предлогом.