python / python/typing

Map with bind: match Tuple of parameterized types with parameters from TypeVarTuple

Ouverte
#1,383 8 commentaires 4 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

topic: feature
Langage dominant
Python
Étoiles
1.8k
Forks
302
Merge moyen
23 h
PR mergées (30 j)
8

Description

Prior work in PEP-646 on Map was dropped to simplify it, with a promise it would appear in a future PEP. Here is a reference to the dropped Map feature: https://github.com/python/typing/issues/193#issuecomment-782689251

Here is an discussion of a potential usage of this Map feature for matching argument types for a length-n Tuple of unary Callables with a length-n Tuple parameterized by a TypeVarTuple: https://groups.google.com/g/dev-python/c/SbPOxIEvI60?pli=1

Here is a draft spec of PEP-646 that included discussion of Map: https://github.com/python/peps/blob/bf897f8c839d1b4d4534ab1fa223a210e2cacf06/pep-0646.rst

I would like to propose an extension of Map with a "bind" argument to allow disambiguation in case the parameterized type has multiple generic parameters. To give an example:

###########
## Converting from multiple domains to a common codomain
############

Domain = TypeVar('Domain')
Codomain = TypeVar('Codomain')

class Detector(Generic(Domain)):
    def __init__(self, detector_fn: Callable[[Any], Optional[Domain]):
        self.detector_fn = detector_fn

    def detect(arg: Any) -> Optional[Domain]
         # returns `arg` if `arg` belongs to Domain, otherwise returns None
        return self.detector_fn(arg)

class Converter(Generic[Domain, Codomain]):
    def __init__(self, converter_fn: Callable[[Domain], Codomain]):
        self.converter_fn = converter_fn

    def convert(arg: Domain) -> Codomain:
        return self.converter_fn(arg)

Domains = TypeVarTuple('Domains')

class ConverterCollection(Generic[*Domains, Codomain]):
    def __init__(self, detectors: Tuple[*Map[Detector, Domains]], converters: Tuple[*Map[Converter, Domains, bind=Domain]]):
        self.detectors = detectors
        self.converters = converters

    def convert(self, obj_to_convert: Union[*Domains]) -> Codomain:
        for detector, converter in zip(self.detectors, self.converters):
            detected_object = detector.detect(obj_to_convert)
            if not (detected_object is None):
                return converter.convert(object_to_convert)
        raise ValueError('No converter for object.')

### Usage

int_detector = Detector[int](lambda x: x if isinstance(x, int) else None)
int_converter = Converter[int, str](lambda x: json.dumps(x))

float_detector = Detector[float](lambda x: x if isinstance(x, float) else None)
float_converter = Converter[float, str](lambda x: json.dumps(x))

cc = ConverterCollection[int, float, str](
    (int_detector, float_detector),
    (int_converter, float_converter)
)

cc.convert(2)    # works
cc.convert(2.0) # also works
cc.convert('hi')  # type error

The bind=Domain argument here would be because Converter class is generic in both Domain and Codomain, so there is ambiguity about which generic parameter to Map. This is not necessary for Detector because, because it is generic only over Domain, so there is no ambiguity what to map over.

Guide de contribution

Aucun guide de contribution indexé pour ce dépôt

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par la discussion abandonnée sur Map dans PEP-646 et le commentaire référencé de typing issue #193, puis lisez la discussion liée sur la mise en correspondance des paramètres Tuple et TypeVarTuple. Déterminez si le bind argument proposé peut être spécifié sans ambiguïté et quel comportement de vérification des types il requiert. Le travail est considéré comme terminé lorsqu’une spécification approuvée ou un plan d’implémentation clairement délimité est produit.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
compilers
Type d'issue
Fonctionnalité
Difficulté
5/5
Temps estimé
Plus d'une semaine
Activité
À l'abandon
Clarté
À clarifier
Accessibilité débutants
20/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.