我有一个 Python 函数,它接受一个数字参数 必须 是一个整数才能正确运行。在 Python 中验证这一点的首选方法是什么?

我的第一反应是做这样的事情:

def isInteger(n):
    return int(n) == n

但我不禁想到,这 1)昂贵 2)丑陋 3)受到机器 epsilon 的温柔怜悯。

Python 是否提供任何类型检查变量的本机方法?或者这是否被认为违反了语言的动态类型设计?

编辑:因为很多人都问过 - 有问题的应用程序使用 IPv4 前缀,从平面文本文件中获取数据。如果任何输入被解析为浮点数,则该记录应被视为格式错误并被忽略。

有帮助吗?

解决方案

isinstance(n, int)

如果你需要知道它是否肯定是一个实际的INT而不是为int的子类(一般情况下不应需要这样做):

type(n) is int

这样:

return int(n) == n

不是一个好主意,如十字型的比较可以是真实的 - 特别是int(3.0)==3.0

其他提示

对,如埃文说,不键入检查。只要尝试使用值:

def myintfunction(value):
   """ Please pass an integer """
   return 2 + value

不具有一个类型检测。这是好多了!让我们看看会发生什么,当我尝试:

>>> myintfunction(5)
7

这工作,因为它是一个整数。嗯。让我们试着一些文本。

>>> myintfunction('text')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in myintfunction
TypeError: unsupported operand type(s) for +: 'int' and 'str'

这显示了一个错误,类型错误,这是它应该做的反正。如果调用者想要赶上,这是可能的。

您会怎么做,如果你做一个类型检测?显示一个错误吗?所以,你不必进行类型检查,因为这个错误已经自动显示出来。

此外,因为你没有进行类型检查,你有你的功能与其他类型的工作:

浮标:

>>> print myintfunction(2.2)
4.2

复数:

>>> print myintfunction(5j)
(2+5j)

小数:

>>> import decimal
>>> myintfunction(decimal.Decimal('15'))
Decimal("17")

即使是号码添加完全是随意的对象!

>>> class MyAdderClass(object):
...     def __radd__(self, value):
...             print 'got some value: ', value
...             return 25
... 
>>> m = MyAdderClass()
>>> print myintfunction(m)
got some value:  2
25

所以,你清楚地得到通过类型检查什么。而失去了很多东西。


更新:

既然你编辑的问题,这是现在很清楚,你的应用程序调用一些例行的上游有意义只能用整数。

既然如此,我仍然认为你应该传递参数的所接收以上游功能。上游函数将处理它正确地例如提高一个错误,如果它需要。我强烈的怀疑您的函数,处理与IP地址的行为很奇怪,如果你传递一个浮动。如果你可以给我们的库的名称,我们可以检查你。

但是...如果上游职能将行为不正确,如果你传递一个浮动杀死一些孩子(我还是很怀疑),那么就只需调用它int()

def myintfunction(value):
   """ Please pass an integer """
   return upstreamfunction(int(value))

你还没有类型检查,所以你得到不类型检查的最大利益。


如果即使在所有这一切,你真正想要的,输入检查,尽管它减少了应用程序的可读性和性能绝对没有好处,使用assert做到这一点。

assert isinstance(...)
assert type() is xxxx

这样,我们可以关闭asserts和删除此<sarcasm> 特征通过调用它作为

从程序</sarcasm>
python -OO program.py
if type(n) is int

此检查是否n是一个Python int和一个int。它不会接受int的子类。

类型检查,但是,不符合“Python的方式”。你最好使用n为int,如果它抛出一个异常,捕获它和行动上面。

Python 现在支持 逐渐打字 通过 打字模块米皮. 。这 typing 从 Python 3.5 开始,模块是 stdlib 的一部分,可以下载 来自 PyPi 如果您需要 Python 2 或以前版本的 Python 3 的向后移植。您可以安装 mypy 通过跑步 pip install mypy 从命令行。

简而言之,如果您想验证某个函数是否接受 int、float 并返回字符串,您可以像这样注释您的函数:

def foo(param1: int, param2: float) -> str:
    return "testing {0} {1}".format(param1, param2)

如果你的文件被命名为 test.py, ,一旦安装了 mypy,你就可以通过运行进行类型检查 mypy test.py 从命令行。

如果您使用的是不支持函数注释的旧版本 Python,则可以使用类型注释来实现相同的效果:

def foo(param1, param2):
    # type: (int, float) -> str
    return "testing {0} {1}".format(param1, param2)

您使用相同的命令 mypy test.py 对于 Python 3 文件,以及 mypy --py2 test.py 对于 Python 2 文件。

Python 解释器在运行时完全忽略类型注释,因此它们会产生最小甚至没有开销——通常的工作流程是处理代码并定期运行 mypy 以捕获错误和错误。某些 IDE(例如 PyCharm)可以理解类型提示,并可以在您直接编辑时提醒您代码中的问题和类型不匹配。

如果出于某种原因,您需要在运行时检查类型(也许您需要验证大量输入?),您应该遵循其他答案中列出的建议 - 例如使用 isinstance, issubclass, ,等等。还有一些库,例如 执行 尝试在运行时执行类型检查(尊重您的类型注释),尽管我不确定它们在撰写本文时的生产准备情况如何。

有关更多信息和详细信息,请参阅 我的网站, , 这 mypy 常见问题解答, , 和 公众号 484.

不要键入检查。鸭打字的整点是,你不应该。举例来说,如果有什么有人做这样的事情:

class MyInt(int):
    # ... extra stuff ...

在Python编程和执行类型检查,你可能会在其他语言似乎就像选择螺丝刀与一鼓作气钉子。这是更优雅的使用Python的异常处理功能。

从一个交互式命令行,则可以运行就像一个语句:

int('sometext')

这将产生错误 - IPython的告诉我:

<type 'exceptions.ValueError'>: invalid literal for int() with base 10: 'sometext'

现在你可以编写一些代码:

try:
   int(myvar) + 50
except ValueError:
   print "Not a number"

这是可以自定义为所需的任何行动,并赶上预期的任何错误。它看起来有点令人费解,但适合在非常可读的代码的语法和Python和结果的成语(一旦你习惯了讲的Python)。

我会被引诱到这样的:

def check_and_convert(x):
    x = int(x)
    assert 0 <= x <= 255, "must be between 0 and 255 (inclusive)"
    return x

class IPv4(object):
    """IPv4 CIDR prefixes is A.B.C.D/E where A-D are 
       integers in the range 0-255, and E is an int 
       in the range 0-32."""

    def __init__(self, a, b, c, d, e=0):
        self.a = check_and_convert(a)
        self.b = check_and_convert(a)
        self.c = check_and_convert(a)
        self.d = check_and_convert(a)
        assert 0 <= x <= 32, "must be between 0 and 32 (inclusive)"
        self.e = int(e)

当你使用它什么都可以但你只能存储一个有效的整数传递的方式。

怎么样:

def ip(string):
    subs = string.split('.')
    if len(subs) != 4:
        raise ValueError("incorrect input")
    out = tuple(int(v) for v in subs if 0 <= int(v) <= 255)
    if len(out) != 4:
        raise ValueError("incorrect input")
    return out

ofcourse有标准isinstance(3,INT)功能...

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top