es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Estrecha Unión por forma

Cómo reducir Union por forma? No quiero verificar los tipos reales con isinstance o una conversión manual (hay muchos tipos). Además, no puedo modificar las definiciones de tipo.

class X:
    title = "1"
class Y:
    name = "2"
class Z:
    name = "3"

for (i, r) in enumerate([X(), Y(), Z()]): # tipo de r: X | Y | Z

    if hasattr(r, "title"):
        print(r.title) # error
    else:
        print(r.name)  # error

El mensaje de error de comprobación de tipo dice:

(variable) título: str | Desconocido
No se puede acceder al miembro “title” para el tipo “Y”
El miembro “title” es desconocido
No se puede acceder al miembro “title” para el tipo “Z”
El miembro “title” es desconocido

(variable) nombre: Desconocido | str
No se puede acceder al miembro “name” para el tipo “X”
El miembro “name” es desconocido
“`

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para limitar una Union por forma sin verificar los tipos reales con isinstance o casting manual, podemos usar el decorador typing.overload para definir diferentes firmas de función para cada forma dentro de la Union. Aquí tienes un ejemplo modificado del código en la pregunta:

    from typing import Union, overload
    
    class X:
        title = "1"
    class Y:
        name = "2"
    class Z:
        name = "3"
    
    @overload
    def my_func(r: X) -> str: pass
    
    @overload
    def my_func(r: Y) -> str: pass
    
    @overload
    def my_func(r: Z) -> str: pass
    
    def my_func(r: Union[X, Y, Z]) -> str:
        if hasattr(r, "title"):
            return r.title  # no error, because we know r has a title attribute
        else:
            return r.name  # no error, because we know r has a name attribute
    
    for (i, r) in enumerate([X(), Y(), Z()]):
        print(my_func(r))  # prints "1", "2", "3"
    

    Aquí utilizamos @overload para definir tres firmas de función diferentes para las tres formas diferentes en la Union[X, Y, Z], lo que permite que Pylance (y otros verificadores de tipos) reduzcan la Union según la forma de la entrada r. Luego, dentro de la implementación de my_func, podemos acceder de manera segura al atributo title o name de r, dependiendo de la forma que tenga. Esto nos permite evitar errores de verificación de tipos y verificar o castear manualmente los tipos.

Comments are closed.