Comments 20
Если честно, по заголовку и описанию рассчитывал прочитать историю (как до этого докатились) аргументов, а тут скорее снимок текущего состояния.
Я бы еще рассказал, что значения по-умолчанию вычисляются один раз — при объявлении функции:
Выведет:
Что еще хитрее:
Выведет:
Т.к. x — это список, изменяемый (mutable) тип, передаваемый по ссылке. И при вызове foo без аргументов передается ссылка на заданный при объявлении foo список, который можно модифицировать внутри функции.
b=1
def foo (a=b):
print (a)
foo()
b=2
foo()
Выведет:
1
1
Что еще хитрее:
def foo (x=[0]):
x[0]+=1
print (x)
foo()
foo()
Выведет:
[1]
[2]
Т.к. x — это список, изменяемый (mutable) тип, передаваемый по ссылке. И при вызове foo без аргументов передается ссылка на заданный при объявлении foo список, который можно модифицировать внутри функции.
Также ничего не сказано об positional-only агрументах
www.python.org/dev/peps/pep-0570
www.python.org/dev/peps/pep-0570
вы бы хоть проверяли свои примеры.
пример с def foo(var, kvar=0, *args,**kwargs):
у вас дан неверно.
я даже сначала подумал, что сам понимаю что-то неправильно.
перепроверил.
таки да — ошибка у вас.
правильно так:
In [1]: def foo(var, kvar=0, *args,**kwargs):
...: print(var, kvar, args, kwargs)
...:
In [2]: foo(1, a=1,)
1 0 () {'a': 1}
In [3]: foo(1, 1)
1 1 () {}
In [4]: foo(1, 2)
1 2 () {}
In [5]: foo(1, 2, a='a', b='b', c='c')
1 2 () {'a': 'a', 'b': 'b', 'c': 'c'}
In [6]: foo(1, 2, 3, a='a', b='b', c='c')
1 2 (3,) {'a': 'a', 'b': 'b', 'c': 'c'}
In [7]: foo(1, 2, 3, a=1, b=2)
1 2 (3,) {'a': 1, 'b': 2}
In [8]: foo(1, 2, a=1, b=2)
1 2 () {'a': 1, 'b': 2}
а у вас в примерах "Вызов 2" и "Вызов 3" даны с ошибками
Еще неучтенный Вами вариантдля пункта «3. Назначение значений аргументов, применяемых по умолчанию»:
def f(a=1, b=2, c=3):
print(a,b,c)
f(1,2,b=4)
Traceback (most recent call last):
File ".../python2.7/site-packages/IPython/core/interactiveshell.py", line 2882, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-10-66b68040163e>", line 1, in <module>
f(1,2,b=4)
TypeError: f() got multiple values for keyword argument 'b'
Хороший пример, недавно попался на похожем, но с передачей кортежа:
def foo(a, b, c=5, *args):
print(a, b, c, args)
cor = (1, 2, 3, 4)
foo(1,2,c=10,*cor)
Получается, что аргумент 'с' ссылается как на именнованный 'с=10', так и на позиционный cor[0].
Возможно, указанные примеры плохого кода?
Я этот код только что на stackoverflow видел, захожу на хабр — он тоже здесь!
ru.stackoverflow.com/questions/1220339/%d0%9e%d1%88%d0%b8%d0%b1%d0%ba%d0%b0-multiple-values-for-argument-%d0%bf%d1%80%d0%b8-%d0%b2%d1%8b%d0%b7%d0%be%d0%b2%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8
ru.stackoverflow.com/questions/1220339/%d0%9e%d1%88%d0%b8%d0%b1%d0%ba%d0%b0-multiple-values-for-argument-%d0%bf%d1%80%d0%b8-%d0%b2%d1%8b%d0%b7%d0%be%d0%b2%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8
Если честно не понятно о чём вообще статья. А «трюки» из первых примеров, которые должны удивить, не удивят никого, что видел книгу по питону. За перевод спасибо, а содержание показалось невнятным.
Мне кажется где-то потерялась четверка.
В остальном спасибо, теперь понятней стало.
foo(1, 2, 3, 4, a=1, b=2) # Вызов 4
# 1 2 (3,) {'a': 1, 'b': 2}
В остальном спасибо, теперь понятней стало.
В тексте оригинальной статьи закралась пара ошибок, перешедших в этот первод, в выводе одной из функций:
def foo(var, kvar=0, *args,**kwargs):
print(var, kvar, args, kwargs)
…
foo(1, 2, a=1, b=2, c=3) # Вызов 2
# 1 0 () {'a': 1, 'b': 2, 'c': 3} – неверно
# 1 2 () {'a': 1, 'b': 2, 'c': 3} – верно
foo(1, 2, 3, a=1, b=2) # Вызов 3
# 1 2 () {'a': 1, 'b': 2} – неверно
# 1 2 (3,) {'a': 1, 'b': 2} – верно
foo(1, 2, 3, 4, a=1, b=2) # Вызов 4
# 1 2 (3,) {'a': 1, 'b': 2} – неверно
# 1 2 (3, 4) {'a': 1, 'b': 2} – верно
Можно добавить, что args и kwargs это всего лишь имена переменных, их можно называть как угодно в ваших функциях.
Если в методе есть необходимость писать подобное foo(var, kvar=0, *args,**kwargs), то явно вы делаете что-то не так…
Автор с первых же строк заметки вводит в блуд читателя, особенно новичков, т.к. например, код:
выведет
Соотв. и в комментарии надо было документировать ИМЕННО ТАКОЕ поведение, а не то которое удобно автору для запутывания читателя и открытия ему СОКРОВЕННЫХ ТАЙН ПОД ПОКРОВАМИ…
def foo(lst):
lst = lst + ['new entry']
print(lst) # Выводит ['Book', 'Pen', 'new entry']
lst = ['Book', 'Pen']
print(lst) # Выводит ['Book', 'Pen']
foo(lst)
print(lst)
выведет
['Book', 'Pen']
['Book', 'Pen', 'new entry']
['Book', 'Pen']
Соотв. и в комментарии надо было документировать ИМЕННО ТАКОЕ поведение, а не то которое удобно автору для запутывания читателя и открытия ему СОКРОВЕННЫХ ТАЙН ПОД ПОКРОВАМИ…
Sign up to leave a comment.
Большая история аргументов функций в Python