Python – Когда вы можете передать позиционный аргумент по имени, а когда вы не можете?

Кажется, что Python 2.7.5 collections.defaultdict работает, когда вы передаете default_factory в качестве позиционного аргумента – он ломается, когда вы передаете его как именованный параметр.

Если вы запустите следующий код, вы увидите, что default_dict_success() работает нормально, но default_dict_failure() бросает KeyError .

 from collections import defaultdict test_data = [ ('clay', 'happy'), ('jason', 'happy'), ('aj', 'sad'), ('eric', 'happy'), ('sophie', 'sad') ] def default_dict_success(): results = defaultdict(list) for person, mood in test_data: results[mood].append(person) print results def default_dict_failure(): results = defaultdict(default_factory=list) for person, mood in test_data: results[mood].append(person) print results default_dict_success() default_dict_failure() 

Выход

 # First function succeeds defaultdict(<type 'list'>, {'sad': ['aj', 'sophie'], 'happy': ['clay', 'jason', 'eric']}) # Second function fails Traceback (most recent call last): File "test_default_dict.py", line 26, in <module> default_dict_failure() File "test_default_dict.py", line 21, in default_dict_failure results[mood].append(person) KeyError: 'happy' 

Кто-нибудь знает, что происходит?

EDIT : Первоначально я думал, что я смотрю на какой-то источник Python, который предположил, что я пытаюсь сделать это возможно, но комментаторы отметили, что я ошибался, поскольку этот объект реализован на C и, следовательно, нет источника Python для этого. Так что это не так загадочно, как я думал.

Это было сказано, это первый раз, когда я столкнулся с позиционным аргументом в Python, который также не мог быть передан по имени. Это происходит в другом месте? Есть ли способ реализовать функцию в чистом Python (в отличие от расширения C), который обеспечивает такой тип поведения?

2 Solutions collect form web for “Python – Когда вы можете передать позиционный аргумент по имени, а когда вы не можете?”

Я думаю, что документы попытаются сказать, что это произойдет, хотя они не особенно ясны:

Первый аргумент предоставляет начальное значение для атрибута default_factory ; по умолчанию используется значение None. Все остальные аргументы обрабатываются так же, как если бы они были переданы конструктору dict, включая аргументы ключевых слов .

Акцент мой. «Первый аргумент» не будет аргументом ключевого слова (у них нет порядка). Тем не менее, подача документации ошибка не будет плохой идеей.

Это было сказано, это первый раз, когда я столкнулся с позиционным аргументом в Python, который также не мог быть передан по имени. Это происходит в другом месте? Есть ли способ реализовать функцию в чистом Python (в отличие от расширения C), который обеспечивает такой тип поведения?

Это на самом деле так распространено, что в нем есть целый ОПТОСОЗ . Рассмотрим range как простой пример.

Что касается этого,

Функции, реализованные в современном Python, могут принимать произвольное количество аргументов только для позиции через параметр Variadic * args. Однако нет синтаксиса Python для указания приема определенного количества параметров только для позиции. Иными словами, существует множество встроенных функций, чьи подписи просто не выражаются с помощью синтаксиса Python.

Можно сделать что-то вроде

 def foo(*args): a, b, c = args 

Это упоминается в PEP:

Очевидно, что можно имитировать любой из них в чистом коде Python, принимая (*args, **kwargs) и анализируя аргументы вручную. Но это приводит к отключению сигнатуры функции Python и тому, что она фактически принимает, не говоря уже о работе по реализации указанного анализа аргументов.

В модулях / _collectionsmodule.c defdict_init () принимает kwargs, но не делает ничего более с ним, чем передает его в PyDict_Type.tp_init ().

IOW, defaultdict документируется как принятие именованного аргумента, но реализация не выполняется, поэтому именованный аргумент передается вместо использования.

Вероятно, это можно было бы исправить с помощью PyArg_ParseTupleAndKeywords, а не рассматривать его аргументы как простой кортеж. Тип deque в том же модуле является примером того, как это можно сделать, поскольку оно принимает пару именованных аргументов.

Я предполагаю, что если вы зарегистрируете ошибку в контролере ошибок Python, либо документ будет изменен в соответствии с реализацией, либо реализация будет изменена в соответствии с документом.

Поддержка деталей – при создании defaultdict с аргументом default_factory с именем, вы получаете словарь, предварительно созданный с помощью default_factory в качестве ключа:

 >>> import collections >>> dd = collections.defaultdict(default_factory=int) >>> dd defaultdict(None, {'default_factory': <class 'int'>}) >>> dd2 = collections.defaultdict(int) >>> dd2 defaultdict(<class 'int'>, {}) >>> 

НТН

  • Невозможно рассортировать defaultdict
  • конвертировать список разделенных строк в дерево / вложенный dict, используя python
  • Создание defaultdict с пустым массивом numpy
  • Доступ к ключу на фабрике defaultdict
  • Зачем вам нужна лямбда для гнезда defaultdict?
  • Совокупные наборы в соответствии с ключами с python defaultdict
  • Как я могу наследовать defaultdict и использовать его метод копирования в методе подкласса?
  • defaultdict эквивалент для списков
  • Python - лучший язык программирования в мире.