如何确保Python中的参数是正确的类型?

siv3szwd  于 2023-05-12  发布在  Python
关注(0)|答案(5)|浏览(192)

我是Python的新手,正在试图弄清楚是否有一种方法可以在参数定义中指定变量类型。例如:

def function(int(integer))

而不是:

def function(integer)
    int(integer)

我知道这不是一个主要的区别,但我试图在这里使用良好的编程实践,如果我定义一个函数有大量的参数,它可能会变得混乱。

hivapdat

hivapdat1#

从Python 3.4开始,你可以为函数或方法添加类型注解:

def function(a: int):
    pass

然而这些类型并不是强制的-你仍然可以用一个非整数的值来调用函数。
此外,Python基于鸭子类型的思想,所以有时候你可能想要接受各种类型,比如intfloat

des4xlb0

des4xlb02#

Python使用Duck typing,这意味着你不应该根据对象的类型来区分它们,而是根据它们的属性和函数来区分它们。这具有许多优点,这些优点超出了本答案的范围。
如果你想给你的函数添加文档,你应该使用一个docstring

def square(x):
    """takes a number and squares it"""
    return x**2

type hints

def square(x: int) -> int:
    """takes a number and squares it"""
    return x**2

如果你真的需要检查给你的参数,你可以执行hasattr()来检查参数提供的属性和函数。在大多数情况下(包括这一个)只是不检查类型是更好的

def square(x):
    """takes a number and squares it"""
    if not hasattr(x, "__pow__"):
         raise TypeError("unsupported operand:", type(x))

    return x**2
yfwxisqw

yfwxisqw3#

如果要使用语法

def function(a: int):
    pass

@SimeonVisser提到过,你有python3.5,你可以使用我写的装饰器

from typing import get_type_hints

def strict_types(f):
    def type_checker(*args, **kwargs):
        hints = get_type_hints(f)

        all_args = kwargs.copy()
        all_args.update(dict(zip(f.__code__.co_varnames, args)))

        for key in all_args:
            if key in hints:
                if type(all_args[key]) != hints[key]:
                    raise Exception('Type of {} is {} and not {}'.format(key, type(all_args[key]), hints[key]))

        return f(*args, **kwargs)

    return type_checker

在定义这样的函数时

@strict_types
def concatenate_with_spam(text: str) -> str:
    return text + 'spam'

如果传递给你的函数的参数类型错误,它会引发异常。

Traceback (most recent call last):
  File "strict_types.py", line 23, in <module>
    concatenate_with_spam(1)
  File "strict_types.py", line 13, in type_checker
    raise Exception('Type of {} is {} and not {}'.format(key, type(all_args[key]), hints[key]))
Exception: Type of text is <class 'int'> and not <class 'str'>

虽然我还没有实现一种方法来检查你返回的类型,如果你也想检查它,这个解决方案不适合你。

vybvopom

vybvopom4#

下面是@ilya-peterov的函数的一个稍微修改的版本,包括检查函数返回值的类型:

def type_checker(f):
"""
A decorator that verifies if the arguments of a function match the specified type.
@param f: the function
@return:
"""

def checker(*args, **kwargs):
    hints = get_type_hints(f)

    all_args = kwargs.copy()
    all_args.update(dict(zip(f.__code__.co_varnames, args)))

    # Check the args type
    for arg_name, arg_value in all_args.items():
        if arg_name in hints:
            expected_type = hints[arg_name]
            # If Union get values
            if hasattr(expected_type, "__origin__") and expected_type.__origin__ == typing.Union:
                expected_type = expected_type.__args__
            msg = f"The `{arg_name}` parameter in `{f.__name__}` function should be an {expected_type} type. " \
                  f"A {type(arg_value)} type was passed instead."
            assert isinstance(arg_value, expected_type), msg

    output = f(*args, **kwargs)

    # Check the output type if specified
    output_type = hints.get('return', None)
    if output_type:
        msg = f"The `{f.__name__}` function should return a {output_type}, " \
              f"but it's returning a {type(output)} instead. " \
              "Please ensure that the return type matches the expected type."
        assert isinstance(output, output_type), msg
    return output

return checker
mzmfm0qo

mzmfm0qo5#

>>> def function(integer :int):
    assert isinstance(integer, int), 'your error message'
    print(integer * integer)

>>> function(3)
    9
>>> function('3')
  Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    function('3')
  File "<pyshell#5>", line 2, in function
    assert isinstance(integer, int), 'your error message'
AssertionError: your error message

相关问题