• notice
  • Congratulations on the launch of the Sought Tech site

Python generic types that implement protocols

Objects A, B...have attributesnamespace , I have a function that passes a specific set of namespacepropertiesvalue to filter the list of such objects:

T=TypeVar('T')


def filter(seq: list[T], namespace_values: set[str])-> list[T]:
    # Returns a smaller list containing only the items from
    # `seq` whose `namespace` are in `namespace_values`
   ...

This works, but it allows passingwithout any checking errorsX Properties of typed objectsnamespace.

I then created a protocol and changed the function to use it:


class Namespaced(Protocol):
    namespace: str

def filter(seq: list[Namespaced], namespace_values: set[str])-> list[Namespaced]:
    # Returns a smaller list containing only the items from
    # `seq` whose `namespace` are in `namespace_values`
   ...

Now if I pass a stringX (this is what I want), I get a check error, but I lose the generic:


list_of_a: list[A]=[a1, a2, a3]

output=filter(list_of_a, ['ns1', 'ns2'])

# output is list[Namespaced] instead of list[A]

How to combine generics and protocols so that my function returns a list of type T, And check whether the project of seq is implemented Namespacedprotocol?

I tried the following but T code> is missing.


def filter(seq: list[Namespaced[T]], namespace_values: set[str])-> list[T]:
    # Returns a smaller list containing only the items from
    # `seq` whose `namespace` are in `namespace_values`
   ...

Cheers!

uj5u.com enthusiastic netizens replied:

Use binding type variables and protocols as bindings.Consider the following modules:

(py39) Juans-MacBook-Pro:~ juan$ cat test.py

There are:

from typing import TypeVar, Protocol
from dataclasses import dataclass

class Namespaced(Protocol):
    namespace: str


T=TypeVar("T", bound="Namespaced")

@dataclass
class Foo:
    namespace: str

@dataclass
class Bar:
    namespace: str
    id: int

def frobnicate(namespaced: list[T])-> list[ T]:
    for x in namespaced:
        print(x.namespace)
    return namespaced

result1=frobnicate([Foo('foo')])
result2=frobnicate([Bar('bar', 1)])

reveal_type(result1)
reveal_type(result2)

Then mypy gives:

(py39) Juans-MacBook-Pro:~ juan$ mypy--strict test.py
test.py:27: note: Revealed type is "builtins.list[test.Foo*]"
test.py:28: note: Revealed type is "builtins.list[test.Bar*]"

Tags

Technical otaku

Sought technology together

Related Topic

0 Comments

Leave a Reply

+