Я думаю, ваша проблема в том, что вы путаете оператор присваивания (=) с оператором равенства (== или ===). оператор присваивания левой руки равен тому, что находится в правой части, а оператор равенства (== или ===) фактически проверяет равенство.
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
В Python, как я могу проанализировать числовую строку, такую как «545.2222», с ее соответствующим значением float, 542.2222? Или проанализировать строку «31» на целое число, 31? Я просто хочу знать, как разбирать строку с плавающей точкой для float и (отдельно) int string для int.
Хорошо, что вы просите сделать это отдельно. Если вы смешиваете их, вы можете настроить себя на проблемы позже. Простой ответ:
"545.2222"
для float:>>> float("545.2222") 545.2222
"31"
для целого числа:>>> int("31") 31
Другие преобразования, ints для и из строк и литералов:
Конверсии из разных баз, и вы должны заранее знать базу (10 по умолчанию). Обратите внимание, что вы можете прикрепить их к тому, что Python ожидает для своих литералов (см. Ниже) или удалить префикс:
>>> int("0b11111", 2) 31 >>> int("11111", 2) 31 >>> int('0o37', 8) 31 >>> int('37', 8) 31 >>> int('0x1f', 16) 31 >>> int('1f', 16) 31
Если вы не знаете базу заранее, но знаете, что они будут иметь Правильный префикс, Python может сделать это для вас, если вы передадите
0
в качестве базы:>>> int("0b11111", 0) 31 >>> int('0o37', 0) 31 >>> int('0x1f', 0) 31
Литералы без десятичного (то есть целого) из других баз
Если ваша мотивация заключается в том, чтобы ваш собственный код четко представлял жестко заданные конкретные значения, однако вам, возможно, не нужно конвертировать из баз - вы можете позволить Python сделать это для вас автоматически с правильным синтаксисом.
Вы можете использовать префиксы apropos для автоматического преобразования в целые числа с следующими литералами . Они действительны для Python 2 и 3:
Binary, prefix
0b
>>> 0b11111 31
Octal, prefix
0o
>>> 0o37 31
Шестнадцатеричный, prefix
0x
>>> 0x1f 31
Это может быть полезно при описании двоичных флагов, разрешений файлов в коде или шестнадцатеричных значений для цветов - например, не отметить кавычки:
>>> 0b10101 # binary flags 21 >>> 0o755 # read, write, execute perms for owner, read & ex for group & others 493 >>> 0xffffff # the color, white, max values for red, green, and blue 16777215
Создание двусмысленных Python 2, совместимых с Python 3
Если вы видите целое число, которое начинается с 0, в Python 2, это (устаревший) восьмеричный синтаксис.
>>> 037 31
Это плохо, потому что похоже, что значение должно быть
37
. Таким образом, в Python 3 теперь появляетсяSyntaxError
:>>> 037 File "<stdin>", line 1 037 ^ SyntaxError: invalid token
Преобразуйте восьмеричные элементы Python 2 в восьмеричные, которые работают как с 2, так и с префиксом
0o
:>>> 0o37 31
def isfloat(value):
try:
float(value)
return True
except:
return False
Более длинным и точным именем для этой функции может быть: isConvertibleToFloat(value)
val isfloat(val) Note
-------------------- ---------- --------------------------------
"" False Blank string
"127" True Passed string
True True Pure sweet Truth
"True" False Vile contemptible lie
False True So false it becomes true
"123.456" True Decimal
" -127 " True Spaces trimmed
"\t\n12\r\n" True whitespace ignored
"NaN" True Not a number
"NaNanananaBATMAN" False I am Batman
"-iNF" True Negative infinity
"123.E4" True Exponential notation
".1" True mantissa only
"1,234" False Commas gtfo
u'\x30' True Unicode is fine.
"NULL" False Null is not special
0x3fade True Hexadecimal
"6e7777777777777" True Shrunk to infinity
"1.797693e+308" True This is max value
"infinity" True Same as inf
"infinityandBEYOND" False Extra characters wreck it
"12.34.56" False Only one dot allowed
u'四' False Japanese '4' is not a float.
"#56" False Pound sign
"56%" False Percent of what?
"0E0" True Exponential, move dot 0 places
0**0 True 0___0 Exponentiation
"-5e-5" True Raise to a negative number
"+1e1" True Plus is OK with exponent
"+1e1^5" False Fancy exponent not interpreted
"+1e1.3" False No decimals in exponent
"-+1" False Make up your mind
"(1)" False Parenthesis is bad
Вы думаете, что знаете, какие цифры? Вы не так хороши, как думаете! Не большой сюрприз.
convertibleToFloat
или что-то подобное (текущее имя кажется запутанным, по крайней мере для меня).
– MKPS
28 August 2016 в 17:07
Это исправленная версия https://stackoverflow.com/a/33017514/5973334
Это попытается проанализировать строку и вернуть либо int
, либо float
в зависимости от того, что представляет строка. Это может привести к синтаксическим ошибкам синтаксического анализа или , которые имеют некоторое неожиданное поведение .
def get_int_or_float(v):
number_as_float = float(v)
number_as_int = int(number_as_float)
return number_as_int if number_as_float == number_as_int else
number_as_float
def num(s):
try:
return int(s)
except ValueError:
return float(s)
/
на float / ints. В зависимости от контекста может быть предпочтительнее возвращать либо int, либо float, а не оба.
– jfs
16 November 2012 в 16:35
try
, чтобы создать исключение, если оно не конвертируется в float.
– iBug
25 January 2018 в 13:31
Python обладает такой большой гибкостью в синтаксическом анализе в одном лайнере.
str = "545.2222"
print ("int: ", + int(float(a)))
print ("float: ", +(float(a)))
def num(s):
"""num(s)
num(3),num(3.7)-->3
num('3')-->3, num('3.7')-->3.7
num('3,700')-->ValueError
num('3a'),num('a3'),-->ValueError
num('3e4') --> 30000.0
"""
try:
return int(s)
except ValueError:
try:
return float(s)
except ValueError:
raise ValueError('argument is not a string of number')
Вы должны рассмотреть возможность запятых в строчном представлении числа, для случаев, подобных float("545,545.2222")
, который выдает исключение. Вместо этого используйте методы в locale
для преобразования строк в числа и правильной интерпретации запятых. Метод locale.atof
преобразуется в float за один шаг после того, как языковой стандарт был установлен для обозначения желаемого номера.
Пример 1 - Соглашения о числах в Соединенных Штатах
В Соединенных Штатах и в Великобритании запятые могут использоваться как разделитель тысяч. В этом примере с американской локалью запятая обрабатывается должным образом в качестве разделителя:
>>> import locale
>>> a = u'545,545.2222'
>>> locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
'en_US.UTF-8'
>>> locale.atof(a)
545545.2222
>>> int(locale.atof(a))
545545
>>>
Пример 2 - Европейские условные обозначения
В большинстве стран world , запятые используются для десятичных знаков вместо периодов. В этом примере с французским языком, запятая корректно обрабатывается как десятичная метка:
>>> import locale
>>> b = u'545,2222'
>>> locale.setlocale(locale.LC_ALL, 'fr_FR')
'fr_FR'
>>> locale.atof(b)
545.2222
Также доступен метод locale.atoi
, но аргумент должен быть целым числом.
Для этого нужно учитывать округление.
I.e. int (5.1) => 5 int (5.6) => 5 - неверно, должно быть 6, поэтому мы делаем int (5.6 + 0.5) => 6
def convert(n):
try:
return int(n)
except ValueError:
return float(n + 0.5)
int
и float
. И это даст исключение, когда n
является строкой, как требуется OP. Возможно, вы имели в виду: Когда желателен результат int
, round
должен быть выполнен ПОСЛЕ конвертации в float. Если функция должна ВСЕГДА возвращать int, тогда вам не нужна за исключением части - тело всей функции может быть int(round(float(input)))
. Если функция должна возвращать int, если это возможно, в противном случае - float, то исходное решение javier будет правильным!
– ToolmakerSteve
13 December 2013 в 08:02
Вот еще одна интерпретация вашего вопроса (намек: он неопределенный). Возможно, вы ищете что-то вроде этого:
def parseIntOrFloat( aString ):
return eval( aString )
Он работает следующим образом ...
>>> parseIntOrFloat("545.2222")
545.22220000000004
>>> parseIntOrFloat("545")
545
Теоретически существует уязвимость в отношении инъекций. Строка может быть, например, "import os; os.abort()"
. Однако, без какой-либо информации о том, откуда взялась эта строка, существует теоретическая спекуляция. Поскольку вопрос неопределен, совершенно неясно, существует ли эта уязвимость или нет.
eval()
превышает 3 раза медленнее, чем try: int(s) except: float(s)
.
– Cees Timmerman
4 October 2012 в 14:12
1e3
- это число в python, но строка в соответствии с вашим кодом.
– Cees Timmerman
4 October 2012 в 14:24
В typecast в python используются функции конструктора типа, передавая строку (или любое другое значение, которое вы пытаетесь выполнить) в качестве параметра.
Например:
>>>float("23.333")
23.333
За кулисами python вызывает метод objects __float__
, который должен возвращать float-представление параметра. Это особенно эффективно, так как вы можете определить свои собственные типы (используя классы) с помощью метода __float__
, чтобы он мог быть введен в float с использованием float (myobject).
float("nan")
- вполне допустимое значение float, которое вышеприведенный ответ не будет вообще поймать
– Ronny Andersson
23 August 2017 в 14:12
Если вы не прочь от сторонних модулей, вы можете проверить модуль fastnumbers . Он предоставляет функцию, называемую fast_real , которая делает именно то, что задает этот вопрос, и делает это быстрее, чем реализация pure-Python:
>>> from fastnumbers import fast_real
>>> fast_real("545.2222")
545.2222
>>> type(fast_real("545.2222"))
float
>>> fast_real("31")
31
>>> type(fast_real("31"))
int
Я использую эту функцию для этого
import ast
def parse_str(s):
try:
return ast.literal_eval(str(s))
except:
return
. Он преобразует строку в свой тип
value = parse_str('1') # Returns Integer
value = parse_str('1.5') # Returns Float
Это еще один метод, который заслуживает упоминания здесь ast.literal_eval :
. Это можно использовать для безопасной оценки строк, содержащих выражения Python, из ненадежных источников без необходимость разбирать значения.
То есть безопасный 'eval'
>>> import ast >>> ast.literal_eval("545.2222") 545.2222 >>> ast.literal_eval("31") 31
python >>> import ast >>> ast.literal_eval('1-800-555-1212') -2566 >>>
Чтобы выяснить, почему это проблема, если вы хотите, чтобы он оставлял номера телефонов в одиночку и не предполагал, что они являются математическими выражениями, тогда этот подход не для вас ,
– royce3
16 January 2018 в 17:14
ast.literal_eval
, и здесь обсуждался .
– wim
16 January 2018 в 18:57
Я удивлен, что никто не упоминает регулярное выражение, потому что иногда строка должна быть подготовлена и нормализована до того, как будет использована функция
import re
def parseNumber(value, as_int=False):
try:
number = float(re.sub('[^.\-\d]', '', value))
if as_int:
return int(number + 0.5)
else:
return number
except ValueError:
return float('nan') # or None if you wish
:
parseNumber('13,345')
> 13345.0
parseNumber('- 123 000')
> -123000.0
parseNumber('99999\n')
> 99999.0
и, кстати, что-то убедитесь, что у вас есть номер:
import numbers
def is_number(value):
return isinstance(value, numbers.Number)
# will work with int, float, long, Decimal
def get_int_or_float(v):
number_as_float = float(v)
number_as_int = int(number_as_float)
return number_as_int if number_as_float == number_as_int else number_as_float
except
, если вы ничего не делаете? float () поднимет вас.
– Greg0ry
19 March 2016 в 21:30
int
, либо float
в зависимости от того, что представляет строка. Это может привести к синтаксическому анализу исключений или [иметь какое-то неожиданное поведение] [1].
– Kuzeko
18 May 2017 в 07:28
int(a)
, аint(float(a))
? – user463035818 26 April 2018 в 14:36int(a)
даст ошибку, что строка не является допустимым целым числом:ValueError: invalid literal for int() with base 10: '545.222'
, но преобразование из float в int является поддерживаемым преобразованием. – David Parks 7 May 2018 в 17:46