[docs] dictionary unpacking `fn(**kwargs)` should accept `SupportsKeysAndGetitem` and not just `Mapping`
Personne n'a encore pris cette issue.
- Langage dominant
- Python
- Étoiles
- 77.2k
- Forks
- 35.9k
- Métriques de merge des PR
- Métriques de PR en attente
Description
Brief
The docs say that for dict unpacking as in fn(**kwargs), kwargs must "implement the methods specified in the collections.abc.Mapping", when in reality only keys() and __getitem__ as in the dict constructor are required.
Documentation
The current documentation states that:
[6.2.5.4. Dictionary displays]
Instead of a key-value pair, a dict item may be an expression prefixed by a double asterisk **. This denotes dictionary unpacking. At runtime, the expression must evaluate to a mapping;
which points to
[mapping]
A container object that supports arbitrary key lookups and implements the methods specified in the collections.abc.Mapping or collections.abc.MutableMapping abstract base classes.
However, at runtime, fn(**kwargs) works whenever kwargs supports both a keys() -> Iterable[str] and __getitem__(self, key: str) -> object method:
class SupportsKeysAndGetitem:
_dict = {"foo": 0, "bar": object()}
def keys(self):
return iter(self._dict)
def __getitem__(self, key: str, /) -> object:
return self._dict[key]
def expects_kwargs(**kwargs: int) -> None:
print(kwargs)
d = SupportsKeysAndGetitem()
expects_kwargs(**d) # works at runtime
Moreover, the relevant methods that Cpython executes under the hood explicitly supports this looser protocol:
class dict
If a positional argument is given and it defines a keys() method, a dictionary is created by calling getitem() on the argument with each returned key from the method.
and
int PyDict_Merge(PyObject *a, PyObject *b, int override)
Part of the Stable ABI. Thread safety: Safe for concurrent use on the same object.
Iterate over mapping object b adding key-value pairs to dictionary a. b may be a dictionary, or any object supporting PyMapping_Keys() and PyObject_GetItem().
Proposal
Update the documentation of dict-unpacking to reflect the actual runtime behavior in sync with how dict construction works, only requiring keys() and __getitem__ rather than inheritance from the non-protocol class collections.abc.Mapping.
Rationale
fn(**kwargs)only requiringkeys()and__getitem__is how it works at runtime, and has since ages- Supporting a protocol is nicer than just supporting a non-protocol ABC like
collections.abc.Mappingdue to duck-typing (a similar conclusion was reached in the discussion of #116938) - There are real world use-cases like
fn(**dataframe)as for example a pandas DataFrame supportskeys()(yields the list of columns) and__getitem__(look up column by name), but does not inherit from thecollections.abc.Mappingclass, nor implements all of its methods.
Linked PRs
- gh-157771
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Examinez la PR liée gh-157771 ainsi que la documentation sur les affichages de Dictionary et le mapping citée dans l’issue. Vérifiez la formulation par rapport au comportement à l’exécution décrit de keys() et getitem ; le travail est terminé lorsque la documentation n’exige plus l’héritage de Mapping et reste cohérente avec la construction de dict.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- python
- Domaine
- documentation
- Type d'issue
- Documentation
- Difficulté
- 1/5
- Temps estimé
- 1-3 heures
- Activité
- À l'abandon
- Clarté
- Clairement spécifiée
- Accessibilité débutants
- 30/100