Почему оба пытаются сделать это "трудным путем"? Что не так с try / кроме?
S.Lott
5
Да, что не так с try / кроме? Лучше просить прощения, чем разрешения.
mk12
53
Я бы спросил, почему эта простая вещь требует попробовать / кроме? Система исключений - сложный зверь, но это простая проблема.
Айвар
13
@ Айвар прекрати распространять ФУД. Один блок try / кроме не подходит даже к «сложному».
Триптих
47
Хотя это не совсем ФУД. Вы бы эффективно написали 4 строки кода, ожидая, что что-то взорвется, поймав это исключение и выполнив заданный по умолчанию вариант, вместо использования одной строки.
Андерсонвом
Ответы:
398
Если вы действительно раздражаетесь от использования try/excepts повсеместно, просто напишите вспомогательную функцию:
Таким образом, это просто для решения простой проблемы со сложным механизмом? Существует алгоритм для обнаружения записанной внутри функции int "int" - я не понимаю, почему это не отображается как булева функция.
Айвар
79
@Aivar: эта пятистрочная функция не является сложным механизмом.
Триптих
34
За исключением:>>> print RepresentsInt(10.0)True>>> print RepresentsInt(10.06)True
Даннид
5
Я думаю, что это «pythonic» в том смысле, что если Python считает, что строка является int, то и ваша программа тоже. Если изменяется Python, то же происходит и с вашей программой без изменения одной строки кода. В этом есть какая-то ценность. Это может быть правильным, в зависимости от обстоятельств.
Shavais
57
Я не знаю, почему это принятый ответ или у него так много откликов, так как это прямо противоположно тому, о чем просит OP.
FearlessFuture
757
с положительными целыми числами вы можете использовать .isdigit:
>>>'16'.isdigit()True
это не работает с отрицательными целыми числами все же. Предположим, вы можете попробовать следующее:
>>> s ='-17'>>> s.startswith('-')and s[1:].isdigit()True
он не будет работать с '16.0'форматом, который похож на intприведение в этом смысле.
это не обрабатывает "+17" без дополнительного специального случая.
Брайан Оукли
1
Вы должны проверить оба случая: лямбда-ы: s.isdigit () или (s.startswith ('-') и s [1:]. Isdigit ())
ограбить
4
@ Роберто: конечно, ты должен! и я уверен, что ты способен на это!
SilentGhost
22
примечание: u'²'.isdigit()верно, но int(u'²')вызывает ValueError. Используйте u.isdecimal()вместо этого. str.isdigit()зависит от языка Python 2.
JFS
4
check_int('')будет False
выдавать
97
Знаете, я обнаружил (и проверял это снова и снова), что попытка / исключение не так хорошо работает по любой причине. Я часто пробую несколько способов сделать что-то, и я не думаю, что я когда-либо нашел метод, который использует try /, кроме как для выполнения лучших из протестированных, на самом деле мне кажется, что эти методы, как правило, приближаются к худший, если не худший. Не в каждом случае, но во многих случаях. Я знаю, что многие люди говорят, что это "Pythonic", но это одна из областей, где я расстаюсь с ними. Для меня это не очень производительно и не очень элегантно, поэтому я склонен использовать его только для отслеживания ошибок и составления отчетов.
Я собирался понять, что в PHP, perl, ruby, C и даже уродливой оболочке есть простые функции для проверки строки на целочисленность, но должная осмотрительность в проверке этих предположений меня смутила! По-видимому, этот недостаток является обычной болезнью.
Вот быстрое и грязное редактирование поста Бруно:
import sys, time, re
g_intRegex = re.compile(r"^([+-]?[1-9]\d*|0)$")
testvals =[# integers0,1,-1,1.0,-1.0,'0','0.','0.0','1','-1','+1','1.0','-1.0','+1.0','06',# non-integers'abc 123',1.1,-1.1,'1.1','-1.1','+1.1','1.1.1','1.1.0','1.0.1','1.0.0','1.0.','1..0','1..','0.0.','0..0','0..','one', object(),(1,2,3),[1,2,3],{'one':'two'},# with spaces' 0 ',' 0.',' .0','.01 ']def isInt_try(v):try: i = int(v)except:returnFalsereturnTruedef isInt_str(v):
v = str(v).strip()return v=='0'or(v if v.find('..')>-1else v.lstrip('-+').rstrip('0').rstrip('.')).isdigit()def isInt_re(v):import re
ifnot hasattr(isInt_re,'intRegex'):
isInt_re.intRegex = re.compile(r"^([+-]?[1-9]\d*|0)$")return isInt_re.intRegex.match(str(v).strip())isnotNonedef isInt_re2(v):return g_intRegex.match(str(v).strip())isnotNonedef check_int(s):
s = str(s)if s[0]in('-','+'):return s[1:].isdigit()return s.isdigit()def timeFunc(func, times):
t1 = time.time()for n in range(times):for v in testvals:
r = func(v)
t2 = time.time()return t2 - t1
def testFuncs(funcs):for func in funcs:
sys.stdout.write("\t%s\t|"% func.__name__)print()for v in testvals:if type(v)== type(''):
sys.stdout.write("'%s'"% v)else:
sys.stdout.write("%s"% str(v))for func in funcs:
sys.stdout.write("\t\t%s\t|"% func(v))
sys.stdout.write("\r\n")if __name__ =='__main__':print()print("tests..")
testFuncs((isInt_try, isInt_str, isInt_re, isInt_re2, check_int))print()print("timings..")print("isInt_try: %6.4f"% timeFunc(isInt_try,10000))print("isInt_str: %6.4f"% timeFunc(isInt_str,10000))print("isInt_re: %6.4f"% timeFunc(isInt_re,10000))print("isInt_re2: %6.4f"% timeFunc(isInt_re2,10000))print("check_int: %6.4f"% timeFunc(check_int,10000))
Метод AC может сканировать его один раз, и будет сделано. Я думаю, что метод AC, который сканирует строку один раз, будет правильным решением.
РЕДАКТИРОВАТЬ:
Я обновил приведенный выше код для работы в Python 3.5, а также для включения функции check_int из ответа, получившего наибольшее количество голосов, и использования текущего наиболее популярного регулярного выражения, которое я могу найти для тестирования на целочисленность. Это регулярное выражение отклоняет строки типа 'abc 123'. Я добавил 'abc 123' в качестве тестового значения.
Мне очень интересно отметить, что на этом этапе ни одна из протестированных функций, включая метод try, популярную функцию check_int и самое популярное регулярное выражение для тестирования целочисленных значений, не возвращает правильных ответов для всех значения теста (ну, в зависимости от того, что вы думаете, правильные ответы; см. результаты теста ниже).
Встроенная функция int () молча обрезает дробную часть числа с плавающей запятой и возвращает целую часть перед десятичной дробью, если только число с плавающей запятой сначала не преобразуется в строку.
Функция check_int () возвращает false для значений, таких как 0.0 и 1.0 (которые технически являются целыми числами), и возвращает true для значений, таких как '06'.
Он работает почти так же, как check_int (0.3486), и возвращает true для значений, таких как 1.0 и 0.0 и +1.0 и 0. и .0 и так далее. Но это также возвращает истину для «06», так что. Выбери свой яд, наверное.
Возможно, отчасти это связано с тем, что целое число само по себе немного произвольно. Система программирования не может позволить себе роскошь предполагать, что она всегда будет десятичным представлением. 0x4df, является допустимым целым числом в некоторых местах, а 0891 нет в других. Я боюсь думать, что может возникнуть при использовании юникода в таких проверках.
PlexQ
3
+1 за время. Я согласен, что весь этот бизнес исключений не очень элегантен для такого простого вопроса. Вы ожидаете встроенный вспомогательный метод для такой распространенной проблемы ...
RickyA
9
Я знаю, что этот поток в основном неактивен, но +1 за рассмотрение времени выполнения. Длина линии не всегда указывает на сложность; и конечно, попробовать / за исключением может выглядеть простой (и читать легко, что тоже немаловажно), но это является дорогостоящей операцией. Я бы сказал, что иерархия предпочтений всегда должна выглядеть примерно так: 1. Легко читаемое явное решение (SilentGhost's). 2. Легко читаемое неявное решение (триптиха). 3. Нет трех.
Эрик Хамфри
1
Спасибо за ваши исследования по такой, казалось бы, незначительной теме. Я пойду с isInt_str (), pythonic или нет. Меня беспокоит то, что я ничего не понял о значении v.find ('..'). Это какой-то особый синтаксис поиска или крайний случай числовой строки?
JackLeEmmerdeur
3
Да, немного устаревший, но все еще очень хороший и актуальный анализ. В Python 3.5 tryэто более эффективно: isInt_try: 0.6552 / isInt_str: 0.6396 / isInt_re: 1.0296 / isInt_re2: 0.5168.
РЕДАКТИРОВАТЬ : Как @BuzzMoschetti указал, этот путь не будет работать для минус число (например, «-23» ). Если ваш input_num может быть меньше 0, используйте re.sub (regex_search, regex_replace, contents) перед применением str.isdigit () . Например:
import re
input_num ="-23"
input_num = re.sub("^-","", input_num)## "^" indicates to remove the first "-" only
str.isdigit(input_num)## True
@ BuzzMoschetti ты прав. Быстрый способ исправить это удалить знак минуса с помощью re.replace (regex_search, regex_replace, content) перед применением str.isdigit ()
Catbuilts
27
Используйте регулярное выражение:
import re
defRepresentsInt(s):return re.match(r"[-+]?\d+$", s)isnotNone
+1: показывает, что это ужасно сложно и дорого по сравнению с попыткой / исключением.
S.Lott
2
Я чувствую, что это, по сути, более медленная, нестандартная версия решения «isnumeric», предлагаемого @SilentGhost.
Грег
@Greg: Поскольку @SilentGhost не покрывает знаки правильно, эта версия действительно работает.
S.Lott
1
@ S.Lott: конечно, любой, кто сможет разместить на SO, сможет расширить мой пример, чтобы охватить знаки.
SilentGhost
2
регулярные выражения - это самая сложная и непонятная вещь в мире, и я обнаружил, что простая проверка, приведенная выше, существенно более понятна, даже если я думаю, что она по-прежнему уродлива, это уродливее.
PlexQ
18
Правильное решение RegEx объединит идеи Грега Хьюгилла и Новелла, но не будет использовать глобальную переменную. Вы можете сделать это, прикрепив атрибут к методу. Кроме того, я знаю, что не рекомендуется помещать импорт в метод, но я собираюсь использовать эффект «ленивого модуля», например http://peak.telecommunity.com/DevCenter/Importing#lazy-imports.
edit: Моя любимая техника до сих пор заключается в использовании исключительно методов объекта String.
#!/usr/bin/env python# Uses exclusively methods of the String objectdef isInteger(i):
i = str(i)return i=='0'or(i if i.find('..')>-1else i.lstrip('-+').rstrip('0').rstrip('.')).isdigit()# Uses re module for regexdef isIntegre(i):import re
ifnot hasattr(isIntegre,'_re'):print("I compile only once. Remove this line when you are confident in that.")
isIntegre._re = re.compile(r"[-+]?\d+(\.0*)?$")return isIntegre._re.match(str(i))isnotNone# When executed directly run Unit Testsif __name__ =='__main__':for obj in[# integers0,1,-1,1.0,-1.0,'0','0.','0.0','1','-1','+1','1.0','-1.0','+1.0',# non-integers1.1,-1.1,'1.1','-1.1','+1.1','1.1.1','1.1.0','1.0.1','1.0.0','1.0.','1..0','1..','0.0.','0..0','0..','one', object(),(1,2,3),[1,2,3],{'one':'two'}]:# Notice the integre uses 're' (intended to be humorous)
integer =('an integer'if isInteger(obj)else'NOT an integer')
integre =('an integre'if isIntegre(obj)else'NOT an integre')# Make strings look like strings in the outputif isinstance(obj, str):
obj =("'%s'"%(obj,))print("%30s is %14s is %14s"%(obj, integer, integre))
И для менее предприимчивых членов класса, вот результат:
I compile only once.Remove this line when you are confident in that.0is an integer is an integre
1is an integer is an integre
-1is an integer is an integre
1.0is an integer is an integre
-1.0is an integer is an integre
'0'is an integer is an integre
'0.'is an integer is an integre
'0.0'is an integer is an integre
'1'is an integer is an integre
'-1'is an integer is an integre
'+1'is an integer is an integre
'1.0'is an integer is an integre
'-1.0'is an integer is an integre
'+1.0'is an integer is an integre
1.1is NOT an integer is NOT an integre
-1.1is NOT an integer is NOT an integre
'1.1'is NOT an integer is NOT an integre
'-1.1'is NOT an integer is NOT an integre
'+1.1'is NOT an integer is NOT an integre
'1.1.1'is NOT an integer is NOT an integre
'1.1.0'is NOT an integer is NOT an integre
'1.0.1'is NOT an integer is NOT an integre
'1.0.0'is NOT an integer is NOT an integre
'1.0.'is NOT an integer is NOT an integre
'1..0'is NOT an integer is NOT an integre
'1..'is NOT an integer is NOT an integre
'0.0.'is NOT an integer is NOT an integre
'0..0'is NOT an integer is NOT an integre
'0..'is NOT an integer is NOT an integre
'one'is NOT an integer is NOT an integre
<object object at 0x103b7d0a0>is NOT an integer is NOT an integre
(1,2,3)is NOT an integer is NOT an integre
[1,2,3]is NOT an integer is NOT an integre
{'one':'two'}is NOT an integer is NOT an integre
Я согласен, что мой набор тестов излишний. Мне нравится доказывать, что мой код работает, когда я его пишу. Но вы думаете, моя функция isInteger излишня? Конечно нет.
Бруно Броноски
1
Я только что получил отрицательный голос без комментариев. Что с людьми? Я понимаю, что миллениалы теперь используют «лайки» как «чеки». Но используют ли они теперь отрицательные голоса в качестве маркеров «не тот метод, который я выбрал»? Возможно, они не понимают, что это вычитает 2 балла из ВАШЕЙ СОБСТВЕННОЙ репутации, чтобы понизить голос за ответ. SO / SE делает это для того, чтобы поощрить голосование только из-за дезинформации, и в этом случае я надеюсь, что вы оставите комментарий .
В подходе Грега Хьюгилла не хватало нескольких компонентов: ведущий «^» соответствовал только началу строки и предварительно компилировал re. Но такой подход позволит вам избежать попытки: exept:
import re
INT_RE = re.compile(r"^[-]?\d+$")defRepresentsInt(s):return INT_RE.match(str(s))isnotNone
Мне было бы интересно, почему вы пытаетесь избежать попробовать: кроме?
Вопрос стиля. Я думаю, что «попробовать / кроме» следует использовать только с фактическими ошибками, а не с нормальным потоком программ.
Адам Матан
2
@Udi Pasmon: Python довольно интенсивно использует try /, за исключением «нормального» потока программ. Например, каждый итератор останавливается с повышенным исключением.
S.Lott
3
-1: Хотя ваш совет по компиляции регулярного выражения верен, вы ошибаетесь в критике Грега в другом отношении: re.match сопоставляется с началом строки, поэтому символ ^ в шаблоне фактически избыточен. (Это отличается, когда вы используете re.search).
ThomasH
С.Лотт - Это считается разумным потоком в питоне? Чем это отличается от других языков? Возможно, стоит отдельный вопрос.
Адам Матан
1
Интенсивное использование в Python try / кроме было рассмотрено здесь на SO. Попробуйте найти «[python] кроме»
S.Lott
4
Я должен делать это все время, и у меня есть легкое, но, по общему признанию, иррациональное отвращение к использованию шаблона «попробуй / кроме». Я использую это:
all([xi in'1234567890'for xi in x])
Он не содержит отрицательных чисел, поэтому вы можете удалить один знак минус (если есть), а затем проверить, содержит ли результат цифры от 0 до 9:
all([xi in'1234567890'for xi in x.replace('-','',1)])
Вы также можете передать x в str (), если вы не уверены, что ввод является строкой:
all([xi in'1234567890'for xi in str(x).replace('-','',1)])
Есть по крайней мере два (край?) Случая, когда это разваливается:
Он не работает для различных научных и / или экспоненциальных обозначений (например, 1.2E3, 10 ^ 3 и т. Д.) - оба возвращают False. Я не думаю, что другие ответы также соответствовали этому, и даже Python 3.8 имеет противоречивые мнения, поскольку type(1E2)дает, <class 'float'>тогда как type(10^2)дает <class 'int'>.
Ввод пустой строки дает True.
Таким образом, он не будет работать для всех возможных входных данных, но если вы можете исключить научную запись, экспоненциальную запись и пустые строки, то это будет однострочная проверка ОК, которая возвращает, Falseесли x не является целым числом и Trueесли x является целым числом.
Я не знаю, является ли это pythonic, но это одна строка, и это относительно ясно, что делает код.
Попытка / исключение выглядит как ходьба по чьей-то лужайке (попытка), а затем, если / когда они замечают и злятся (исключение), вы приносите свои извинения (обрабатываете исключение), тогда как мой all(xi in '1234567890' for xi in x])шаблон больше похож на просьбу разрешить пройти по лужайке. Я не в восторге от того, что спрашиваю разрешения, но мы здесь.
Угадай, что replaceделает? Кроме того, это будет неправильно принимать 5-2, например.
Ry-
Выкинет IndexError, еслиs='-'
Anti Earth
s = '-'; s.replace ('-', '') .isdigit () -> False
Владислав Савченко
2
Мне очень понравился пост Шавайса, но я добавил еще один тестовый пример (и встроенную функцию isdigit ()):
def isInt_loop(v):
v = str(v).strip()# swapping '0123456789' for '9876543210' makes nominal difference (might have because '1' is toward the beginning of the string)
numbers ='0123456789'for i in v:if i notin numbers:returnFalsereturnTruedef isInt_Digit(v):
v = str(v).strip()return v.isdigit()
и это значительно последовательно бьет время отдыха:
Оба тестовых примера, которые я добавил (isInt_loop и isInt_digit), проходят одинаковые тестовые примеры (они оба принимают только целые числа без знака), но я подумал, что люди могут быть более умными с изменением реализации строки (isInt_loop) в отличие от встроенного isdigit (), поэтому я включил ее, хотя есть небольшая разница во времени выполнения. (и оба метода намного превосходят все остальное, но не обрабатывают лишние вещи: "./+/-")
Кроме того, мне было интересно отметить, что регулярное выражение (метод isInt_re2) побеждает сравнение строк в том же тесте, который был выполнен Shavais в 2012 году (в настоящее время 2018). Может быть, библиотеки регулярных выражений были улучшены?
Это, пожалуй, самый простой и питонный способ приблизиться к этому, на мой взгляд. Я не видел это решение, и оно в основном такое же, как и регулярное выражение, но без регулярного выражения.
set(input_string) == set(string.digits)если мы пропускаем '-+ 'в начале и .0, E-1в конце концов.
Jfs
1
Вот функция, которая анализирует без возникновения ошибок. Он обрабатывает очевидные случаи возврата Noneпри сбое (по умолчанию обрабатывает до 2000 знаков '- / +' на CPython!):
#!/usr/bin/env pythondef get_int(number):
splits = number.split('.')if len(splits)>2:# too many splitsreturnNoneif len(splits)==2and splits[1]:# handle decimal part recursively :-)if get_int(splits[1])!=0:returnNone
int_part = splits[0].lstrip("+")if int_part.startswith('-'):# handle minus sign recursively :-)return get_int(int_part[1:])*-1# successful 'and' returns last truth-y value (cast is always valid)return int_part.isdigit()and int(int_part)
Некоторые тесты:
tests =["0","0.0","0.1","1","1.1","1.0","-1","-1.1","-1.0","-0","--0","---3",'.3','--3.',"+13","+-1.00","--+123","-0.000"]for t in tests:print"get_int(%s) = %s"%(t, get_int(str(t)))
Безопасно оцените узел выражения или строку, содержащую литерал Python или отображение контейнера. Предоставленная строка или узел могут состоять только из следующих литеральных структур Python: строк, байтов, чисел, кортежей, списков, диктов, множеств, логических значений и None.
Я должен отметить, что это вызовет ValueErrorисключение при вызове против всего, что не является литералом Python. Поскольку вопрос задан для решения без попытки / кроме, у меня есть решение типа Кобаяси-Мару для этого:
from ast import literal_eval
from contextlib import suppress
def is_int(s):with suppress(ValueError):return isinstance(literal_eval(s), int)returnFalse
Я предполагаю, что вопрос связан со скоростью, так как попытка / исключение имеет штраф за время:
данные испытаний
Сначала я создал список из 200 строк, 100 строк с ошибками и 100 строк с цифрами.
from random import shuffle
numbers =[u'+1']*100
nonumbers =[u'1abc']*100
testlist = numbers + nonumbers
shuffle(testlist)
testlist = np.array(testlist)
решение numpy (работает только с массивами и юникодом)
np.core.defchararray.isnumeric также может работать со строками Unicode, np.core.defchararray.isnumeric(u'+12')но он возвращает и массив. Таким образом, это хорошее решение, если вам нужно выполнить тысячи преобразований и у вас отсутствуют данные или не числовые данные.
import numpy as np
%timeit np.core.defchararray.isnumeric(testlist)10000 loops, best of 3:27.9µs per loop # 200 numbers per loop
попробовать / за исключением
def check_num(s):try:
int(s)returnTrueexcept:returnFalsedef check_list(l):return[check_num(e)for e in l]%timeit check_list(testlist)1000 loops, best of 3:217µs per loop # 200 numbers per loop
Ответы:
Если вы действительно раздражаетесь от использования
try/except
s повсеместно, просто напишите вспомогательную функцию:Это будет ПУТЬ больше кода, чтобы точно охватить все строки, которые Python считает целыми числами. Я говорю просто будь питоническим на этом.
источник
>>> print RepresentsInt(10.0)
True
>>> print RepresentsInt(10.06)
True
с положительными целыми числами вы можете использовать
.isdigit
:это не работает с отрицательными целыми числами все же. Предположим, вы можете попробовать следующее:
он не будет работать с
'16.0'
форматом, который похож наint
приведение в этом смысле.редактировать :
источник
u'²'.isdigit()
верно, ноint(u'²')
вызывает ValueError. Используйтеu.isdecimal()
вместо этого.str.isdigit()
зависит от языка Python 2.check_int('')
будетFalse
Знаете, я обнаружил (и проверял это снова и снова), что попытка / исключение не так хорошо работает по любой причине. Я часто пробую несколько способов сделать что-то, и я не думаю, что я когда-либо нашел метод, который использует try /, кроме как для выполнения лучших из протестированных, на самом деле мне кажется, что эти методы, как правило, приближаются к худший, если не худший. Не в каждом случае, но во многих случаях. Я знаю, что многие люди говорят, что это "Pythonic", но это одна из областей, где я расстаюсь с ними. Для меня это не очень производительно и не очень элегантно, поэтому я склонен использовать его только для отслеживания ошибок и составления отчетов.
Я собирался понять, что в PHP, perl, ruby, C и даже уродливой оболочке есть простые функции для проверки строки на целочисленность, но должная осмотрительность в проверке этих предположений меня смутила! По-видимому, этот недостаток является обычной болезнью.
Вот быстрое и грязное редактирование поста Бруно:
Вот результаты сравнения производительности:
Метод AC может сканировать его один раз, и будет сделано. Я думаю, что метод AC, который сканирует строку один раз, будет правильным решением.
РЕДАКТИРОВАТЬ:
Я обновил приведенный выше код для работы в Python 3.5, а также для включения функции check_int из ответа, получившего наибольшее количество голосов, и использования текущего наиболее популярного регулярного выражения, которое я могу найти для тестирования на целочисленность. Это регулярное выражение отклоняет строки типа 'abc 123'. Я добавил 'abc 123' в качестве тестового значения.
Мне очень интересно отметить, что на этом этапе ни одна из протестированных функций, включая метод try, популярную функцию check_int и самое популярное регулярное выражение для тестирования целочисленных значений, не возвращает правильных ответов для всех значения теста (ну, в зависимости от того, что вы думаете, правильные ответы; см. результаты теста ниже).
Встроенная функция int () молча обрезает дробную часть числа с плавающей запятой и возвращает целую часть перед десятичной дробью, если только число с плавающей запятой сначала не преобразуется в строку.
Функция check_int () возвращает false для значений, таких как 0.0 и 1.0 (которые технически являются целыми числами), и возвращает true для значений, таких как '06'.
Вот текущие (Python 3.5) результаты теста:
Только сейчас я попытался добавить эту функцию:
Он работает почти так же, как check_int (0.3486), и возвращает true для значений, таких как 1.0 и 0.0 и +1.0 и 0. и .0 и так далее. Но это также возвращает истину для «06», так что. Выбери свой яд, наверное.
источник
try
это более эффективно: isInt_try: 0.6552 / isInt_str: 0.6396 / isInt_re: 1.0296 / isInt_re2: 0.5168.str.isdigit()
должен сделать свое дело.Примеры:
РЕДАКТИРОВАТЬ : Как @BuzzMoschetti указал, этот путь не будет работать для минус число (например, «-23» ). Если ваш input_num может быть меньше 0, используйте re.sub (regex_search, regex_replace, contents) перед применением str.isdigit () . Например:
источник
Используйте регулярное выражение:
Если вы должны принять десятичные дроби также:
Для повышения производительности, если вы делаете это часто, скомпилируйте регулярное выражение только один раз, используя
re.compile()
.источник
Правильное решение RegEx объединит идеи Грега Хьюгилла и Новелла, но не будет использовать глобальную переменную. Вы можете сделать это, прикрепив атрибут к методу. Кроме того, я знаю, что не рекомендуется помещать импорт в метод, но я собираюсь использовать эффект «ленивого модуля», например http://peak.telecommunity.com/DevCenter/Importing#lazy-imports.
edit: Моя любимая техника до сих пор заключается в использовании исключительно методов объекта String.
И для менее предприимчивых членов класса, вот результат:
источник
Таким образом, ваша функция будет:
источник
В подходе Грега Хьюгилла не хватало нескольких компонентов: ведущий «^» соответствовал только началу строки и предварительно компилировал re. Но такой подход позволит вам избежать попытки: exept:
Мне было бы интересно, почему вы пытаетесь избежать попробовать: кроме?
источник
Я должен делать это все время, и у меня есть легкое, но, по общему признанию, иррациональное отвращение к использованию шаблона «попробуй / кроме». Я использую это:
Он не содержит отрицательных чисел, поэтому вы можете удалить один знак минус (если есть), а затем проверить, содержит ли результат цифры от 0 до 9:
Вы также можете передать x в str (), если вы не уверены, что ввод является строкой:
Есть по крайней мере два (край?) Случая, когда это разваливается:
type(1E2)
дает,<class 'float'>
тогда какtype(10^2)
дает<class 'int'>
.Таким образом, он не будет работать для всех возможных входных данных, но если вы можете исключить научную запись, экспоненциальную запись и пустые строки, то это будет однострочная проверка ОК, которая возвращает,
False
если x не является целым числом иTrue
если x является целым числом.Я не знаю, является ли это pythonic, но это одна строка, и это относительно ясно, что делает код.
источник
all(xi in '1234567890' for xi in x])
шаблон больше похож на просьбу разрешить пройти по лужайке. Я не в восторге от того, что спрашиваю разрешения, но мы здесь.Я думаю
было бы лучше переписать на:
потому что s [1:] также создает новую строку
Но гораздо лучшее решение
источник
replace
делает? Кроме того, это будет неправильно принимать5-2
, например.s='-'
Мне очень понравился пост Шавайса, но я добавил еще один тестовый пример (и встроенную функцию isdigit ()):
и это значительно последовательно бьет время отдыха:
используя обычный 2.7 питон:
Оба тестовых примера, которые я добавил (isInt_loop и isInt_digit), проходят одинаковые тестовые примеры (они оба принимают только целые числа без знака), но я подумал, что люди могут быть более умными с изменением реализации строки (isInt_loop) в отличие от встроенного isdigit (), поэтому я включил ее, хотя есть небольшая разница во времени выполнения. (и оба метода намного превосходят все остальное, но не обрабатывают лишние вещи: "./+/-")
Кроме того, мне было интересно отметить, что регулярное выражение (метод isInt_re2) побеждает сравнение строк в том же тесте, который был выполнен Shavais в 2012 году (в настоящее время 2018). Может быть, библиотеки регулярных выражений были улучшены?
источник
Это, пожалуй, самый простой и питонный способ приблизиться к этому, на мой взгляд. Я не видел это решение, и оно в основном такое же, как и регулярное выражение, но без регулярного выражения.
источник
set(input_string) == set(string.digits)
если мы пропускаем'-+ '
в начале и.0
,E-1
в конце концов.Вот функция, которая анализирует без возникновения ошибок. Он обрабатывает очевидные случаи возврата
None
при сбое (по умолчанию обрабатывает до 2000 знаков '- / +' на CPython!):Некоторые тесты:
Результаты:
Для своих нужд вы можете использовать:
источник
Я предлагаю следующее:
Из документов :
Я должен отметить, что это вызовет
ValueError
исключение при вызове против всего, что не является литералом Python. Поскольку вопрос задан для решения без попытки / кроме, у меня есть решение типа Кобаяси-Мару для этого:¯ \ _ (ツ) _ / ¯
источник
У меня есть одна возможность, которая вообще не использует int, и не должна вызывать исключение, если строка не представляет число
Это должно работать для любого вида строк, которые могут принимать плавающие, положительные, отрицательные, инженерные обозначения ...
источник
Я предполагаю, что вопрос связан со скоростью, так как попытка / исключение имеет штраф за время:
данные испытаний
Сначала я создал список из 200 строк, 100 строк с ошибками и 100 строк с цифрами.
решение numpy (работает только с массивами и юникодом)
np.core.defchararray.isnumeric также может работать со строками Unicode,
np.core.defchararray.isnumeric(u'+12')
но он возвращает и массив. Таким образом, это хорошее решение, если вам нужно выполнить тысячи преобразований и у вас отсутствуют данные или не числовые данные.попробовать / за исключением
Кажется, что решение NumPy намного быстрее.
источник
Если вы хотите принимать только младшие цифры, вот тесты для этого:
Python 3.7+:
(u.isdecimal() and u.isascii())
Python <= 3.6:
(u.isdecimal() and u == str(int(u)))
Другие ответы предлагают использовать
.isdigit()
или,.isdecimal()
но оба они включают некоторые символы верхнего юникода, такие как'٢'
(u'\u0662'
):источник
int()
.Э-э .. Попробуйте это:
Это работает, если вы не поместите строку, которая не является числом.
А также (я забыл поставить часть проверки номера.), Есть функция, проверяющая, является ли строка числом или нет. Это str.isdigit (). Вот пример:
Если вы вызовете a.isdigit (), он вернет True.
источник
2
присвоенногоa
.