代码之家  ›  专栏  ›  技术社区  ›  Chris Conlan

如何在python3中向自定义静态类型提示传递参数?

  •  1
  • Chris Conlan  · 技术社区  · 6 年前

    我是Python3的忠实粉丝,并且主张使用静态类型提示。我已经用了一段时间没有问题了。

    例如,这在Python 3中很常见:

    from typing import List, NewType
    CustomObject = NewType('CustomObject', List[int])
    
    def f(data: List[CustomObject]):
        # do something
    

    class MyContainer():
        # some class definition ...
    
    from typing import NewType
    SpecialContainer = NewType('SpecialContainer', MyContainer)
    
    def f(data: SpecialContainer[str]):
        # do something
    

    我知道了 SpecialContainer 在本例中,从技术上讲是一个函数,但不应将其作为类型签名上下文中的函数进行计算。第二个代码段失败 TypeError: 'function' object is not subscriptable .

    1 回复  |  直到 6 年前
        1
  •  3
  •   Chris Conlan    6 年前

    编译我的代码示例

    必须从头开始设计类以接受静态类型提示。这不符合我最初的用例,因为我试图声明第三方类的特殊子类型,但它编译了我的代码示例。

    from typing import Generic, TypeVar, Sequence, List
    
    # Declare your own accepted types for your container, required
    T = TypeVar('T', int, str, float)
    
    # The custom container has be designed to accept types hints
    class MyContainer(Sequence[T]):
        # some class definition ...
    
    # Now, you can make a special container type
    # Note that Sequence is a generic of List, and T is a generic of str, as defined above
    SpecialContainer = TypeVar('SpecialContainer', MyContainer[List[str]])
    
    # And this compiles
    def f(data: SpecialContainer):
        # do something
    

    子类型化第三方类

    f() ,拍了一张照片 pd.DataFrame 对象,该对象由整数索引,其单元格均为字符串。利用上面的答案,我想出了一个巧妙的表达方式。

    from typing import Mapping, TypeVar, NewType, NamedTuple
    from pandas import pd
    
    # Create custom types, required even if redundant
    Index = TypeVar('Index')
    Row = TypeVar('Row')
    
    # Create a child class of pd.DataFrame that includes a type signature
    # Note that Mapping is a generic for a key-value store
    class pdDataFrame(pd.DataFrame, Mapping[Index, Row]):
        pass
    
    # Now, this compiles, and explains what my special pd.DataFrame does
    pdStringDataFrame = NewType('pdDataFrame', pdDataFrame[int, NamedTuple[str]])
    
    # And this compiles
    def f(data: pdStringDataFrame):
        pass
    

    • 如果您正在编写一个类似于容器泛型的自定义类,比如 Sequence , Mapping Any

    • 如果您试图对未实现类型提示的第三方类的特定用法进行注释:

      • 尝试使用现有的类型变量来理解你的观点,例如。 MyOrderedDictType = NewType('MyOrderedDictType', Dict[str, float])
      • 如果这样做不起作用,您将不得不用琐碎的子类和类型变量来混乱您的命名空间,以获得要编译的类型提示。最好使用docstring或注释来解释您的情况。