在大多数情况下,我喜欢这样一个事实:你可以选择任何类型并将它放在你喜欢的Python中,然后让Duck打字接管。但是如何通过编译时间来阻止这种糟糕的事情。有没有办法在编译时需要执行某种健全性检查,而不需要求助于单元测试。
答案 0 :(得分:4)
使用像Pychecker这样的单独工具来警告您使用不存在的方法或属性。这不是编译的一部分,但您可以将其强制执行,作为您自己的流程的一部分,例如VCS中的预提交挂钩。
答案 1 :(得分:3)
没有。 Python编译器不会(通常不能)知道你是否正确拼写了变量名,更不用说每个变量,对象属性,集合槽等中的pup类型。这不仅仅是因为编写它的人有其他优先级,大多数代码都很难实现。对于一些非常简单的情况,静态分析仪可能会尝试这样的事情。但实际上,这是不可能的。
答案 2 :(得分:3)
答案 3 :(得分:1)
Python并没有真正定义其他静态语言的“编译时”。
您可以使用isinstance()
和type()
来验证您的对象是否是您期望的类的实例。
答案 4 :(得分:1)
你可以让所有东西的第一行类似:
if not all(isinstance(a, b) for a, b in zip(((x, int), (y, str), (z, float))))
您可以使用像http://code.enthought.com/projects/traits/这样的包,允许您显式声明类型。
您可以在http://cython.org/中编写代码。
答案 5 :(得分:1)
Python没有这样的东西,因为编译是初始化时间。您可以使用assert
语句来强制将特定类型传递给您的函数,即assert type(foo) == list
,但这有点不合理,因为它首先打败了鸭子打字的地步。什么是pythonic是检查以确保您获得的对象具有您需要的方法。例如,如果您需要迭代对象,请尝试以下操作:
assert '__iter__' in dir(obj)
答案 6 :(得分:1)
您可以滥用装饰器,在调试模式下为异常类型添加警告:
import warnings
import functools
import numbers
debug = True
class TypeWarning(Warning):
pass
def warn_types(*pos_types):
def decorator(func):
if not debug:
return func
@functools.wraps(func)
def wrapper(*args):
for i, (x, t) in enumerate(zip(args, pos_types)):
if not isinstance(x, t):
warnings.warn("Expected %s got %s for argument %d of %s"
% (t.__name__, x.__class__.__name__,
i, func.__name__),
category=TypeWarning, stacklevel=2)
return func(*args)
return wrapper
return decorator
@warn_types(numbers.Number, numbers.Number)
def add(x, y):
return x + y
这会在不破坏功能的情况下为程序员发出警告,并且可以通过关闭调试模式来关闭它们。在完成项目编码后,也可以通过简单的搜索替换删除它们。
>>> print add(3, 4)
7
>>> print add("a", "b")
__main__:1: TypeWarning: Expected Number got str for argument 0 of add
__main__:1: TypeWarning: Expected Number got str for argument 1 of add
ab
在一般情况下,为关键字参数扩展这一点并非易事,除非你使用Python 3并且可以利用注释,以防它变得非常简单。
答案 7 :(得分:0)
我想你只想要快速检查,对吧?
我将以快速演示回答:
>>> m = 7
>>> m.__class__
<type 'int'>
>>> n = 6
>>> o = 6.6
>>> m.__class__ == n.__class__
True
>>> m.__class__ == o.__class__
False
>>> isinstance(o, int)
False
>>> isinstance(m, int)
True
>>>
希望这是有道理的。