除非我弄错了,在Python中创建一个函数是这样的:

def my_func(param1, param2):
    # stuff

但是,实际上并没有给出这些参数的类型。而且,如果我没记错的话,Python是一种强类型语言,因此,Python似乎不应该让你传入与函数创建者期望的不同类型的参数。然而,Python如何知道函数的用户正在传递正确的类型呢?假设函数实际使用了形参,如果它是错误的类型,程序会死吗?必须指定类型吗?


当前回答

您不需要指定类型。该方法只有在试图访问未在传入参数上定义的属性时才会失败(在运行时)。

这个简单的函数:

def no_op(param1, param2):
    pass

... 无论传入哪两个参数都不会失败。

然而,这个函数:

def call_quack(param1, param2):
    param1.quack()
    param2.quack()

... 如果param1和param2都没有名为quack的可调用属性,将在运行时失败。

其他回答

从静态或编译时类型检查的意义上讲,Python不是强类型的。

大多数Python代码都属于所谓的“Duck Typing”——例如,你寻找一个对象上读取的方法——你不关心对象是磁盘上的文件还是套接字,你只想从中读取N个字节。

你从不指定类型;Python有鸭子类型的概念;基本上,处理参数的代码将对参数做出某些假设——可能通过调用参数期望实现的某些方法。如果参数类型错误,则会引发异常。

一般来说,这取决于你的代码来确保你传递的对象是正确类型的——没有编译器提前强制这一点。

我在其他答案中没有看到这个,所以我把这个加到锅里。

正如其他人所说,Python不会对函数或方法参数强制执行类型。假设您知道自己在做什么,如果您确实需要知道传入的内容的类型,您将检查它并决定自己要做什么。

完成此任务的主要工具之一是isinstance()函数。

例如,如果我编写了一个希望获得原始二进制文本数据的方法,而不是普通的utf-8编码字符串,那么我可以在进入时检查参数的类型,并根据所找到的参数进行调整,或者引发一个异常来拒绝。

def process(data):
    if not isinstance(data, bytes) and not isinstance(data, bytearray):
        raise TypeError('Invalid type: data must be a byte string or bytearray, not %r' % type(data))
    # Do more stuff

Python还提供了各种深入对象的工具。如果您足够勇敢,甚至可以使用importlib动态地为任意类创建自己的对象。我这样做是为了从JSON数据重新创建对象。这样的事情在像c++这样的静态语言中是一场噩梦。

要有效地使用typing模块(Python 3.5新增),请包含all(*)。

from typing import *

你将准备使用:

List, Tuple, Set, Map - for list, tuple, set and map respectively.
Iterable - useful for generators.
Any - when it could be anything.
Union - when it could be anything within a specified set of types, as opposed to Any.
Optional - when it might be None. Shorthand for Union[T, None].
TypeVar - used with generics.
Callable - used primarily for functions, but could be used for other callables.

然而,你仍然可以使用类型名称,如int, list, dict,…

您不需要指定类型。该方法只有在试图访问未在传入参数上定义的属性时才会失败(在运行时)。

这个简单的函数:

def no_op(param1, param2):
    pass

... 无论传入哪两个参数都不会失败。

然而,这个函数:

def call_quack(param1, param2):
    param1.quack()
    param2.quack()

... 如果param1和param2都没有名为quack的可调用属性,将在运行时失败。