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


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.