在python中检查函数参数的类型

checking type of the parameters of a function in python

首先,我意识到这是Python社区中争论的一个源头,即类型检查表示代码不好等等。然而,这是我学习经验的一部分,我希望在我的Python工具集中有另一种技能。

1
2
3
4
5
6
7
8
def do_plus(a,b):
    result=a+b
    return result
calculated_result=do_plus(12,34567)
print (calculated_result)

calculated_result=do_plus(12,34567)
print (calculated_result)

现在,当我尝试时:

1
2
type(calculated_result)
type (do_plus)

我分别得到int和function。

1
type (do_plus(a))

上述结果导致:

1
2
3
4
"Traceback (most recent call last):
  File"
<pyshell#9>", line 1, in <module>
    type (do_plus(a,b))
NameError: name 'a' is not defined"

我对此感到困惑,我肯定在def do_plus后面的括号中定义了a和b?

我需要参数类型的原因是要进行抽样检查,即检查类型,如果不正确,则引发类型错误,遗憾的是,我似乎在第一个跨栏处失败了:(


我认为您的问题来自对变量类型如何在Python中工作的误解。在线中

1
type(do_plus(a))

它抱怨a没有被定义的原因是它没有查看参数a,而是在寻找一个名为a的变量,它试图传递给函数。

在Python中,方法参数不是强类型的。您不能只通过查看签名就知道方法需要什么类型!我假设您来自一种静态类型语言,在这种语言中,您可以使用反射或类似的技巧来检查为该方法声明的参数,但是在Python中不存在这样的功能,因为它没有意义。例如,我可以这样做:

1
2
3
4
5
6
7
8
9
10
do_plus(1, 2) # parameters are both `int`
>>> 3
do_plus(1.1, 2.2) # parameters are both `float`
>>> 3.3
do_plus("string1","string2") # parameters are both `str`
>>>"string1string2"
do_plus("string", 3) # one parameter is `str`, one is `int`
>>>"string3"
do_plus(3,"string")
>>> TypeError: unsupported operand type(s) for +: 'int' and 'str'

注意,在最后一行,投诉不是"你不能用这些参数调用这个方法",而是"我不知道如何计算3 +"string""。如果查看堆栈跟踪,它会抱怨do_plus中的行,这表明执行成功地进入了函数。

因此,由于不能从函数外部键入check,因此必须在函数内部键入check。您可以使用isinstance内置功能来完成此操作:

1
2
3
4
def do_plus(a, b):
  if not isinstance(a, int) or not isinstance(b, int):
    raise TypeError("do_plus only accepts ints")
  return a + b

这是因为Python的一个核心指导原则:"请求原谅比请求允许要好。"与其检查自己是否能做些什么,不如尝试去做并处理失败。

其他音符

你写type (doplus(a))的方式告诉我你认为type是某种关键字。不是这样的,type是一个函数。实际上,它不仅仅是一个函数,它还是一个函数。你可以写

1
2
type(type)
>>> <type 'type'>

这会让你得出结论:type实际上是一种类型!类型为type!这一切很快就会变得非常混乱,但关键是,在Python中很少有单词被保留为关键字。在其他语言中,大多数作为关键字的功能都是通过内置函数完成的。

另外,我看到您已经了解了这一点,但一般来说,您不想检查类型,只想尝试做一些事情,如果成功的话,那么hurray!这就是"鸭子打字的好处",意思是"如果它长得像鸭子,嘎嘎叫得像鸭子,那就是鸭子"。你应该假设人们传递到你的函数中的任何参数都能够支持你试图对它们执行的操作;这样人们就可以传递到其他支持相同操作的对象中,从理论上讲,他们会得到一个同样合理的结果。这是一种推理方法逻辑而不是实现的方法;问题应该是"我做的是正确的事情吗?"不是"这做得对吗?"

希望这对你有帮助。Python是一种非常好的、非常灵活的语言,但它要求您的思维方式与其他语言的思维方式大不相同。


在代码变量A中,B在方法do_plus的本地范围内。

为了更好地理解它,让print(type(a))在方法中:

1
2
3
4
def do_plus(a, b):
    print(type(a), type(b))
    result = a + b
    return result

所以如果我调用do_plus(1, 2)输出是:

1
2
<class 'int'> <class 'int'>
3

但如果我调用do_plus(1.1, 2.0)输出是:

1
2
<class 'float'> <class 'float'>
3.1

你看,A,B的类型不存在,因为A和B没有定义。它们只声明为变量。

当调用该方法并向a传递float时,它将变为float。当a通过一个int时,它变为int。

另一个例子是我们定义b=2

1
2
3
4
def do_plus(a, b=2):
    print(type(a), type(b))
    result = a + b
    return result

这里,如果向b传递一个值,不管它是float、int还是boolean。b将是该变量的数据类型。

只有当b不传递一个值时,我们才能100%确定b是方法do_plus中的一个int。

这是Python的不同核心部分。理解这一点的一个好方法是:

1
2
3
4
5
6
7
a = 10
print(type(a))
a = 10.1
print(type(a))

<class 'int'>
<class 'float'>

当变量a被分配一个int时,它的数据类型是int。当它被分配一个float时,它的数据类型变为float。


您的问题实际上与检查参数类型无关。这完全是关于变量范围。

这些变量ab是函数的局部变量,仅在函数运行时存在。一旦函数返回,它们就没有意义了。如果要打印涉及这些变量的任何内容,请向函数中添加代码以执行此操作。