Подтвердить что ты не робот

Как я могу проверить тип переменных в Python?

У меня есть функция Python, которая принимает числовой аргумент, который должен быть целым числом, чтобы он вел себя корректно. Каков предпочтительный способ проверки этого в Python?

Моя первая реакция - сделать что-то вроде этого:

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

Но я не могу не думать о том, что это 1) дорогой 2) уродливый и 3) с учетом нежных милостей машинного эпсилона.

Предоставляет ли Python какие-либо собственные средства переменных проверки типов? Или это считается нарушением языка динамически типизированного дизайна?

РЕДАКТИРОВАТЬ: поскольку многие люди спрашивали - приложение, о котором идет речь, работает с префиксами IPv4, используя данные из текстовых файлов. Если какой-либо вход обрабатывается в float, эта запись должна рассматриваться как некорректная и игнорироваться.

4b9b3361

Ответ 1

isinstance(n, int)

Если вам нужно знать, действительно ли это фактический int, а не подкласс int (обычно вам не нужно это делать):

type(n) is int

return int(n) == n

не такая хорошая идея, как могут быть сопоставления между типами - особенно int(3.0)==3.0

Ответ 2

Да, как сказал Эван, не набирайте чек. Просто попробуйте использовать значение:

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

У этого нет typecheck. Это намного лучше! Посмотрим, что произойдет, когда я попробую:

>>> 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'

Он показывает ошибку, TypeError, что и должно делать в любом случае. Если вызывающий абонент хочет поймать это, это возможно.

Что бы вы сделали, если бы вы сделали typecheck? Сообщить об ошибке Поэтому вам не нужно проверять тип, потому что ошибка уже отображается автоматически.

Плюс, так как вы не проверили typecheck, у вас есть функция, работающая с другими типами:

Поплавки:

>>> 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

Таким образом, вы явно ничего не получаете путем проверки типов. И потерять много.


UPDATE:

Поскольку вы отредактировали вопрос, теперь стало ясно, что ваше приложение вызывает некоторую восходящую процедуру, которая имеет смысл только с помощью int.

В этом случае я все же думаю, что вы должны передать параметр , полученный, в функцию восходящего потока. Функция восходящего потока будет правильно работать с ней, например. при возникновении ошибки, если это необходимо. Я сильно сомневаюсь, что ваша функция, которая имеет дело с IP-адресами, будет вести себя странно, если вы передадите ей float. Если вы можете дать нам имя библиотеки, мы можем проверить это для вас.

Но... Если восходящая функция будет вести себя некорректно и убьет некоторых детей, если вы передадите ей поплавок (я все еще очень сомневаюсь в этом), просто просто назовите int() на нем:

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

Вы по-прежнему не проверяете typecheck, поэтому получаете больше преимуществ от проверки типов.


Если даже после всего этого вы действительно хотите напечатать чек, несмотря на то, что это уменьшает читаемость и производительность приложений без какой-либо выгоды, используйте assert для этого.

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

Таким образом мы можем отключить assert и удалить эту функцию <sarcasm> </sarcasm> из программы, назвав ее как

python -OO program.py

Ответ 3

if type(n) is int

Это проверяет, является ли n Python int и только int. Он не будет принимать подклассы int.

Проверка типов, однако, не соответствует "Python way". Лучше использовать n как int, и если он выдает исключение, поймайте его и действуйте по нему.

Ответ 4

Python теперь поддерживает постепенное печатание через набор текста и mypy. Модуль typing является частью stdlib с Python 3.5 и может быть загружен из PyPi, если вам нужны backports для 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 и тому подобное. Существуют также некоторые библиотеки, такие как enforce, которые пытаются выполнить проверку типов (с учетом аннотаций типа) во время выполнения, хотя я не уверен, как готовые к изготовлению они относятся к моменту написания.

Для получения дополнительной информации и информации см. сайт mypy, mypy FAQ и PEP 484.

Ответ 5

Не вводите проверку. Весь смысл утиной печати - это то, что вам не нужно. Например, что, если кто-то сделал что-то вроде этого:

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

Ответ 6

Программирование на Python и выполнение typechecking, как вы могли бы на других языках, похоже на выбор отвертки для подбивки гвоздя. Более элегантно использовать функции обработки исключений 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).

Ответ 7

Я был бы склонен к чему-то вроде:

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)

Таким образом, когда вы используете его, все может быть передано, но вы сохраняете только действительное целое число.

Ответ 8

как насчет:

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

конечно, существует стандартная функция isinstance (3, int)...