Гола зірочка в аргументах функції?


242

Що робить гола зірочка в аргументах функції?

Коли я подивився на модуль соління , то бачу таке:

pickle.dump(obj, file, protocol=None, *, fix_imports=True)

Я знаю про одиничні та подвійні зірочки, що передують аргументам (для змінної кількості аргументів), але це нічого не передує. І я майже впевнений, що це не має нічого спільного з солінням. Це, мабуть, лише приклад цього. Я дізнався її назву лише тоді, коли надіслав це перекладачеві:

>>> def func(*):
...     pass
...
  File "<stdin>", line 1
SyntaxError: named arguments must follow bare *

Якщо це має значення, я на python 3.3.0.


Відповіді:


221

Bare *використовується, щоб змусити абонента використовувати названі аргументи - тому ви не можете визначити функцію *в якості аргументу, коли у вас немає наступних аргументів ключового слова.

Дивіться цю відповідь або документацію Python 3 для отримання більш детальної інформації.


3
Зауважте, що всі позиційні (безіменні) аргументи, в тому числі *args, повинні виникати перед голою *.
BallpointBen

4
Також зауважте, що існує свого роду аналог, / який позначає кінець аргументами, які мають лише позицію ( stackoverflow.com/questions/28243832/… ).
Стівен

2
@BallpointBen: *на місці *args, і навпаки; вони не можуть співіснувати в підписі. Тому вони обрали *; раніше це *argsбув єдиний спосіб примусити суто позиційні аргументи, і це означало закінчення аргументів, які можна було б передавати позиційно (оскільки він зібрав усі інші позиційні аргументи, вони могли дійти до наступних названих аргументів). *означає той же «позиційний аргумент не може вийти за рамки тут», але відсутність імені означає «але я їх взагалі не прийму, тому що вирішив не надавати місця для їх розміщення».
ShadowRanger

70

Хоча оригінальна відповідь відповідає на питання повністю, лише додавши трохи пов’язаної інформації. Поведінка для єдиної зірочки випливає з PEP-3102. Цитуючи відповідний розділ:

The second syntactical change is to allow the argument name to
be omitted for a varargs argument. The meaning of this is to
allow for keyword-only arguments for functions that would not
otherwise take a varargs argument:

    def compare(a, b, *, key=None):
        ...

Простий англійською мовою, це означає, що для передачі значення для ключа вам потрібно буде явно передати його як key="value".


О, це робить речі набагато зрозумілішими. Так що насправді мати аргумент * так само, як мати аргументи аргументу *, але оскільки ви нічого цього не назвали, його єдиний ефект - це, ймовірно, тихо збивати всі інші позиційні аргументи, щоб змусити решта аргументів бути ключовими словами -тільки.
Стівен

11
@Stephen Я теж спочатку думав, що ефект голого *полягає в тому, щоб збивати залишилися позиційні аргументи, але це не так. Передача додаткових позиційних аргументів, ніж очікує функція, дає помилку такого типу:foo() takes exactly 1 positional argument (2 given)
Ajay M

19
def func(*, a, b):
    print(a)
    print(b)

func("gg") # TypeError: func() takes 0 positional arguments but 1 was given
func(a="gg") # TypeError: func() missing 1 required keyword-only argument: 'b'
func(a="aa", b="bb", c="cc") # TypeError: func() got an unexpected keyword argument 'c'
func(a="aa", b="bb", "cc") # SyntaxError: positional argument follows keyword argument
func(a="aa", b="bb") # aa, bb

наведений вище приклад із ** kwargs

def func(*, a, b, **kwargs):
    print(a)
    print(b)
    print(kwargs)

func(a="aa",b="bb", c="cc") # aa, bb, {'c': 'cc'}

6

Семантично це означає, що наведені нижче аргументи є лише ключовими словами, тому ви отримаєте помилку, якщо спробуєте надати аргумент, не вказуючи його ім'я. Наприклад:

>>> def f(a, *, b):
...     return a + b
...
>>> f(1, 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes 1 positional argument but 2 were given
>>> f(1, b=2)
3

Прагматично це означає, що вам потрібно викликати функцію аргументом ключового слова. Зазвичай це робиться тоді, коли важко буде зрозуміти мету аргументу без натяку на ім'я аргументу.

Порівняйте, наприклад, sorted(nums, reverse=True)якщо ви писали sorted(nums, True). Останнє було б набагато менш читабельним, тому розробники Python вирішили змусити вас написати це колишнім способом.


4

Припустимо, у вас є функція:

def sum(a,key=5):
    return a + key 

Цю функцію можна викликати двома способами:

sum(1,2) або sum(1,key=2)

Припустимо, ви хочете, щоб функція sumвикликалася лише за допомогою аргументів ключових слів.

Ви додаєте *до списку параметрів функції, щоб позначити кінець позиційних аргументів.

Отже функція визначається як:

def sum(a,*,key=5):
    return a + key 

може називатися лише за допомогою sum(1,key=2)


-1

Я знайшов наступне посилання, яке дуже корисно пояснює *, *argsі **kwargs:

https://pythontips.com/2013/08/04/args-and-kwargs-in-python-explained/

По суті, окрім наведених вище відповідей, я дізнався з вищевказаного сайту (кредит: https://pythontips.com/author/yasoob008/ ) наступне:

Функція демонстрації, визначена спочатку нижче, є два приклади: один з *argsі один із**kwargs

def test_args_kwargs(arg1, arg2, arg3):
    print "arg1:", arg1
    print "arg2:", arg2
    print "arg3:", arg3

# first with *args
>>> args = ("two", 3,5)
>>> test_args_kwargs(*args)
arg1: two
arg2: 3
arg3: 5

# now with **kwargs:
>>> kwargs = {"arg3": 3, "arg2": "two","arg1":5}
>>> test_args_kwargs(**kwargs)
arg1: 5
arg2: two
arg3: 3

Таким чином, *argsви зможете динамічно складати список аргументів, які будуть прийняті в тому порядку, в якому вони подаються, тоді як **kwargsможуть дозволити передачу аргументів NAMED і можуть бути оброблені відповідно NAME (незалежно від порядку, в якому вони подаються) .

Сайт продовжується, зазначаючи, що правильне впорядкування аргументів повинно бути:

some_func(fargs,*args,**kwargs)

2
Ця відповідь майже не має нічого спільного з питанням. Це навіть використання застарілої версії python, яка не має цієї функції.
Антті
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.