除非我弄错了,在Python中创建一个函数是这样的:
def my_func(param1, param2):
# stuff
但是,实际上并没有给出这些参数的类型。而且,如果我没记错的话,Python是一种强类型语言,因此,Python似乎不应该让你传入与函数创建者期望的不同类型的参数。然而,Python如何知道函数的用户正在传递正确的类型呢?假设函数实际使用了形参,如果它是错误的类型,程序会死吗?必须指定类型吗?
除非我弄错了,在Python中创建一个函数是这样的:
def my_func(param1, param2):
# stuff
但是,实际上并没有给出这些参数的类型。而且,如果我没记错的话,Python是一种强类型语言,因此,Python似乎不应该让你传入与函数创建者期望的不同类型的参数。然而,Python如何知道函数的用户正在传递正确的类型呢?假设函数实际使用了形参,如果它是错误的类型,程序会死吗?必须指定类型吗?
当前回答
在Python中,所有东西都有类型。如果参数类型支持,Python函数将执行它被要求执行的任何操作。
示例:foo将添加所有可以__add__ed;)的东西,而不太关心它的类型。这意味着,为了避免失败,你应该只提供那些支持加法的东西。
def foo(a,b):
return a + b
class Bar(object):
pass
class Zoo(object):
def __add__(self, other):
return 'zoom'
if __name__=='__main__':
print foo(1, 2)
print foo('james', 'bond')
print foo(Zoo(), Zoo())
print foo(Bar(), Bar()) # Should fail
其他回答
您不需要指定类型。该方法只有在试图访问未在传入参数上定义的属性时才会失败(在运行时)。
这个简单的函数:
def no_op(param1, param2):
pass
... 无论传入哪两个参数都不会失败。
然而,这个函数:
def call_quack(param1, param2):
param1.quack()
param2.quack()
... 如果param1和param2都没有名为quack的可调用属性,将在运行时失败。
我在其他答案中没有看到这个,所以我把这个加到锅里。
正如其他人所说,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++这样的静态语言中是一场噩梦。
Alex Martelli解释道,
正常的、Pythonic的、首选的解决方案几乎总是“duck typing”:尝试使用参数,好像它是某种所需的类型,在try/except语句中执行它,捕捉如果参数实际上不是该类型(或任何其他类型,很好地模仿它;-)可能出现的所有异常,并在except子句中尝试其他内容(使用参数“as if”它是其他类型)。
阅读他的文章以获得有用的信息。
无论您是否指定类型提示,都将在运行时失败。
However, you can provide type hints for both function arguments and its return type. For example, def foo(bar: str) -> List[float] hints that bar is expected to be a string and the function returns a list of float values. This will result in a type check error when the method is invoked if the types don't match (before the use of the parameter in the function, or of the return type). This IMOHO is much more helpful in catching such errors vs an error about a missing field or method somewhere in the method call. I recommend reading the official Python documentation Typing - Support for type hints.
此外,如果使用类型提示,则可以使用静态类型检查器来验证代码的正确性。python中内置的一个这样的工具是myypy(官方文档)。关于静态类型检查的文章的这一部分很好地介绍了如何使用它。
Python是强类型的,因为每个对象都有一个类型,每个对象都知道它的类型,不可能意外或故意使用一个类型的对象,“好像”它是一个不同类型的对象,对象上的所有基本操作都委托给它的类型。
这和名字无关。Python中的名称没有“类型”:如果定义了名称,则名称指向对象,并且对象确实具有类型(但这实际上并不强制名称具有类型:名称就是名称)。
A name in Python can perfectly well refer to different objects at different times (as in most programming languages, though not all) -- and there is no constraint on the name such that, if it has once referred to an object of type X, it's then forevermore constrained to refer only to other objects of type X. Constraints on names are not part of the concept of "strong typing", though some enthusiasts of static typing (where names do get constrained, and in a static, AKA compile-time, fashion, too) do misuse the term this way.