【问题标题】:Using Python type hints to specify that a type should be just that?使用 Python 类型提示来指定一个类型应该就是那个?
【发布时间】:2021-04-06 04:07:33
【问题描述】:

我可以像这样使用 Python 的类型系统吗?

def myFunc(type : type, any):

使得以下是该函数的有效使用。

myFunc(int, 4)
myFunc(float, "abc")
myFunt(myClass, [2, [4, "six"]])

但这不是。

myFunc(2, 3)

如果这不可能,我是否可以通过要求对象具有构造函数或要求类型为类或内置类型来实现类似的功能?

def myFunc(type : has(__init__), any):
def myFunc(type : POD or Class, any):

【问题讨论】:

  • 你为什么要这样做?传递给函数的变量类型不是很明显吗?您也可以在已经通过后检查类型。 python 中不需要类型定义。
  • 我真的很喜欢鸭式打字,以及 Python 的优雅程度。我从这一切中得到的印象是答案就是不这样做,并假设函数的用户可以读取参数名称,并从具有合理属性的输入值中读取。
  • @alan2here。这就是为什么你应该编写好的文档。知道名称和预期类型通常并不比只知道名称好多少。
  • 您在这里的最终要求是什么? myFunc 在实践中会是什么?

标签: python python-3.x types type-hinting


【解决方案1】:

你想要的都可以通过使用装饰器来完成。

我可以通过要求对象具有构造函数或要求类型为类或内置类型来实现类似的功能

首先定义一个装饰器(一个做你想做的事情的函数,让你在调用之前处理参数或对函数做任何你想做的事情)

def decorator(function):
    def wrapper(*args, **kwargs): # the function that does the checks
        # you can do the same for any keyword arguments
        for argument in args:
            if hasattr(argument, "__init__"): 
                print(f'Argument {argument} has an __init__ method')
        return function(*args, **kwargs)
    return wrapper

然后你可以将它应用到任何函数中

@decorator
def myFunction(some_argument):
    return None

例如,如果您使用int 调用myFunction,您将获得以下信息

In [18]: myFunction(3)
Argument 3 has an __init__ method

我可以像这样使用 Python 的类型系统吗? ... 这样以下是该函数的有效用法。

您可以在装饰器内部检查 __anotations__ 中传递的函数的 this 问题并验证每个输入。 __anotations__ 返回一个字典,用键指定变量的名称和类型注释的值。一个简单的例子是

def decorator(function):
    def wrapper(*args, **kwargs):
        # {'a': <class 'str'>, 'b': <class 'int'>}
        type_hints = function.__annotations__ 
        
        # kwargs is a dictionary so
        # if a and b are parameters whose values are hello and
        # 2 then the dict is {a: "hello", b: 2}
        for keyword in kwargs:
            assert type(kwargs.get(keyword)) == type_hints.get(keyword)

        # also check on the list args
        for index, argument in enumerate(args):
            assert type(argument) == type_hints[list(type_hints)[index]]

        return function(*args, **kwargs)
    return wrapper

@decorator
def myFunc(a: str, b: int):
    return a, b

现在您可以按如下方式调用该函数,并且仅当类型提示与每个函数参数的类型匹配时它才会起作用

In [42]: myFunc("hello", 1)
Out[42]: ('hello', 1)
In [43]: myFunc(1, 2)
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-43-8bd42ff057a5> in <module>
----> 1 myFunc(1, 2)
# ... the rest of the traceback

【讨论】:

  • FWIW,如果您只对静态类型感兴趣,则不需要使用装饰器。装饰器可以使用类型注释很好,但如果您使用类型注释,您通常需要静态类型检查器来验证它们,而不是运行时装饰器。
  • 如果您正在编写一个没有任何速度要求并且希望类型正确的库,则不能依赖“用户”输入。如果您想在运行前检查函数是否被正确调用,那么 python 不是正确的选择,也许执行这种验证的编译语言会更好。除非你有一个强大的 IDE 来做这种事情。
  • "如果你想在运行前检查函数是否被正确调用,那么 python 不是正确的选择" 类型提示的重点是允许第三方静态类型检查器来做这件事。例如,您可以使用mypy
猜你喜欢
  • 2023-03-29
  • 2021-06-15
  • 2016-02-29
  • 2012-12-23
  • 1970-01-01
  • 2016-08-17
  • 2022-12-19
  • 2023-04-02
相关资源
最近更新 更多