Bir dizeyi bir kayan noktaya veya int'e nasıl ayrıştırabilirim?


2251

Python'da, "545.2222"karşılık gelen kayan nokta değerine benzer bir sayısal dizeyi nasıl ayrıştırabilirim 545.2222? Ya dizeyi ayrıştırmak "31", bir tam sayıya 31?

Sadece ayrıştırmak nasıl bilmek istiyorum şamandıra str bir etmek floatve (ayrı) bir int str bir etmek int.


7
Genel bir kural olarak, Python bir nesne var ve dönüştürmek istiyorsanız için , nesnenin o tip çağrısı type(my_object)üzerine. Sonuç genellikle dönüşümü yapmak için bir işlev olarak çağrılabilir. Örneğin type(100)sonuç verir int, böylece bir tam sayıya int(my_object)dönüştürmeyi denemek için arayabilirsiniz my_object. Bu her zaman işe yaramaz, ancak kodlama sırasında iyi bir "ilk tahmin" tir.
robertlayton

int(x) if int(x) == float(x) else float(x)
tcpaiva

Yanıtlar:


2623
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545

8
Sonunda neden '04' olduğunu merak ediyor musunuz? neden sadece '00' olmasın? ayrıca şu anki python versiyonumda '04' yok.
Mangat Rai Modi

54
@MangatRaiModi Kayan nokta sayıları ondalık sayıları temsil etmek için doğal olarak kusurludur. Daha fazla bilgi için bkz. Stackoverflow.com/q/21895756/931277
dokkaebi

19
neden sadece int(a)değil int(float(a))?
idclev 463035818

24
int(a)dizenin geçerli bir tamsayı olmadığı bir hata verir: ValueError: invalid literal for int() with base 10: '545.222'ancak bir kayan noktadan int değerine dönüştürmek desteklenen bir dönüştürme işlemidir.
David Parks

4
ValueErrorGüvende olmak istiyorsanız başa
çıkmalısınız

515
def num(s):
    try:
        return int(s)
    except ValueError:
        return float(s)

81
örtülü karıştırma şamandıraları / ints şamandıralarla çalışırken olası hassasiyet kaybı nedeniyle ince hatalara veya /şamandıralar / ints üzerinde operatör için farklı sonuçlara yol açabilir . Bağlama bağlı olarak, her ikisini değil, int veya float döndürmek tercih edilebilir.
jfs

14
@JFSebastian Tamamen haklısınız, ancak girdinin hangisinin olacağını dikte etmesini istediğiniz zamanlar var. Girdinin, ördek yazma ile hangisinin güzel çalışabileceğini dikte etmesine izin vermek.
TimothyAWiseman

4
tryŞamandıra dönüştürülemediğinde bir istisna atmak için başka bir yuva yerleştirebilirsiniz .
iBug

2
Başarısızs = u'\u0000'
Matt Hancock

1
@iBug İyi fikir! Ben ValueErrorkarşılık gelen atma öneririz except: P
marcelm

511

Bir dizenin kayan nokta olup olmadığını kontrol etmek için Python yöntemi:

def is_float(value):
  try:
    float(value)
    return True
  except:
    return False

Bu işlev için daha uzun ve daha doğru bir ad şunlar olabilir: is_convertible_to_float(value)

Python'da bir şamandıra nedir ve bir şamandıra sizi şaşırtabilir:

val                   is_float(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

Numaraların ne olduğunu bildiğini mi sanıyorsun? Sandığınız kadar iyi değilsiniz! Büyük sürpriz değil.

Bu kodu hayati öneme sahip yazılımlarda kullanmayın!

Geniş istisnaları bu şekilde yakalamak, kanaryaları öldürmek ve istisnayı azaltmak, dize olarak geçerli bir şamandıranın yanlış dönmesi için küçük bir şans yaratır. float(...)Kod satırının dizesinin içeriğiyle ilgisi olmayan bin nedenlerden herhangi birine başarısız olabilir. Ancak, hayat açısından kritik bir yazılımı Python gibi ördek tipi bir prototip dilde yazıyorsanız, çok daha büyük sorunlarınız var.


1
Yani gerçek 1 olur, sanırım C ++ 'dan miras alınır
FindOutIslamNow

6
2014 yılında bu cevabı yayınladım. UTF-8Bir Çinli için bu glif, 4stackoverflow geliştiricilerinin karakter kodlama şemasını microsoft tooltack'larına nasıl değiştirdiğine bağlı olarak yıllar içinde değişiyor. Yeni dönüşüm planları yeni ideolojilerini öne sürdüğü için yıllar boyunca flopları ters çevirmek bir meraktır. Ama evet, UTF-8Doğu oryantal sayısal için herhangi bir glif bir Python şamandıra değildir. Bazinga.
Eric Leschinski

4
bu kadar geniş bir istisna dışında nasıl bu kadar iyi değerlendirilebilir?
E.Serra

Aralarında boşluk olan her şey, "- 12.3"ve gibi dönüştürülemez"45 e6"
Simon

1
Bu fıkra hariç olmakla sınırlandırılmalıdırTypeError, ValueError
wim

131

Bu, burada belirtilmeyi hak eden başka bir yöntemdir, ast.literal_eval :

Bu, değerleri kendileri ayrıştırmaya gerek kalmadan, güvenilmeyen kaynaklardan Python ifadeleri içeren dizeleri güvenle değerlendirmek için kullanılabilir.

Yani, güvenli bir 'eval'

>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31

11
bu sorun için iyi bir çözüm değildir . Python 2'de iyi çalışıyor, ancak Python 3'te aşağıdakiler oluyor: python >>> import ast >>> ast.literal_eval('1-800-555-1212') -2566 >>> Bunun neden bir sorun olduğunu açıklamak için, telefon numaralarını yalnız bırakmasını ve matematiksel ifadeler olduklarını varsaymamasını istiyorsanız, bu yaklaşım sizin için değildir.
royce3

6
@ royce3 Evet, bu iyi bir nokta ve kullanıcılar dikkat etmeli. Davranış başlangıçta karmaşık değişmezlerin ayrıştırılmasıyla ilgili bazı sorunları gidermek için değiştirildi. Bu muhtemelen bir hata ast.literal_evalve burada tartışıldı .
wim

79
float(x) if '.' in x else int(x)

21
Not: Bazı ülkeler ondalık ayırıcı olarak "," kullandığından, dize olarak geçirilen para tutarıyla ilgilenirken dikkatli olun
Ben G

127
@Emile: "2e-3" e "aşırı durum" demezdim. Bu cevap kırılmış.
jchl

14
@BenG Şamandıra olarak parayı manipüle ETMEYİN. Bu bela istiyor. Para için ondalık kullanın! (Ancak ',' hakkındaki yorumunuz hala geçerli ve önemlidir)
ToolmakerSteve

4
"Bir sayı değil" (NaN) ve +/- sonsuzluğunun da geçerli kayan değer olduğunu unutmayın. Yani float("nan")yukarıdaki cevabı hiç yakalamak olmaz mükemmel geçerli şamandıra değerdir
Ronny Andersson

2
Bir IP adresi ile kolayca kırılabilir - 192.168.0.1; veya"This is not a good approach. :)"
Todor Minakov

69

Yerelleştirme ve virgül

float("545,545.2222")İstisna atanan durumlar için, bir sayının dize gösteriminde virgül olasılığını göz önünde bulundurmalısınız . Bunun yerine, localedizeleri sayılara dönüştürmek ve virgülleri doğru yorumlamak için yöntemleri kullanın . locale.atofYerele kez tek bir adımda bir şamandıra yöntem dönüştürür istenen sayıda kuralı için ayarlandı.

Örnek 1 - Birleşik Devletler sayı sözleşmeleri

Amerika Birleşik Devletleri ve Birleşik Krallık'ta, virgüller binlerce ayırıcı olarak kullanılabilir. Amerikan yerel ayarına sahip bu örnekte, virgül ayırıcı olarak düzgün kullanılır:

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

Örnek 2 - Avrupa sayı sözleşmeleri

Dünya ülkelerinin çoğunda virgül, nokta yerine ondalık işareti için kullanılır. Fransızca yerel ayarlı bu örnekte, virgül ondalık işareti olarak doğru şekilde işlenir:

>>> import locale
>>> b = u'545,2222'
>>> locale.setlocale(locale.LC_ALL, 'fr_FR')
'fr_FR'
>>> locale.atof(b)
545.2222

Yöntem locale.atoide kullanılabilir, ancak argüman bir tamsayı olmalıdır.


Bu, bir kayan nokta veya int döndürülüp döndürülmeyeceğini bildiğinizde ideal bir çözüm gibi görünür, ancak bunu yalnızca int geçirilmişse int döndürmek için nasıl edinebilirsiniz? Örneğin, gerçekten istediğim zaman x = '1'; locale.atof(x)geri döner . 1.01
user5359531

Dino yöntemini kullanarak, cevap böyle bir şey kullanmak olacaktır sanırım:locale.atof(x) if locale.localeconv().get('decimal_point') in x else locale.atoi(x)
user5359531

Yukarıda Javier'in yöntemini kullanmanızı tavsiye ederim ( locale.atoibir deneme locale.atof
yapıyorum

27

Üçüncü taraf modüllere karşı değilseniz, fastnumbers modülünü kontrol edebilirsiniz . Bu sorunun tam olarak ne istediğini yapan ve salt Python uygulamasından daha hızlı yapan fast_real adlı bir işlev sağlar :

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

24

Kullanıcılar codelogic ve harley doğrudur, ancak dizenin bir tamsayı olduğunu biliyorsanız (örneğin, 545), önce yüzmek için döküm yapmadan int ("545") diyebilirsiniz.

Dizeleriniz bir listede bulunuyorsa, harita işlevini de kullanabilirsiniz.

>>> x = ["545.0", "545.6", "999.2"]
>>> map(float, x)
[545.0, 545.60000000000002, 999.20000000000005]
>>>

Sadece hepsi aynı türdeyse iyi olur.


21

Python'da "545.2222" gibi sayısal bir dizeyi 542.2222 karşılık gelen kayan noktalı değere nasıl ayrıştırabilirim? Veya "31" dizesini 31, Ben sadece bir kayan nokta için bir kayan nokta dize ayrıştırmak ve bir int için (ayrı ayrı) bir int string bilmek istiyorum.

Bunları ayrı ayrı yapmanız iyi olur. Onları karıştırıyorsanız, daha sonra sorunlara hazırlıklı olabilirsiniz. Basit cevap:

"545.2222" Batmak:

>>> float("545.2222")
545.2222

"31" bir tamsayıya:

>>> int("31")
31

Diğer dönüşümler, dizgilere ve değişmez metinlere giriş ve çıkışlar:

Çeşitli bazlardan dönüşümler ve tabanı önceden bilmeniz gerekir (10 varsayılan değerdir). Bunlara Python'un değişmez değerleri için ne beklediğini ön ekleyebilir (aşağıya bakın) veya ön eki kaldırabilirsiniz:

>>> int("0b11111", 2)
31
>>> int("11111", 2)
31
>>> int('0o37', 8)
31
>>> int('37', 8)
31
>>> int('0x1f', 16)
31
>>> int('1f', 16)
31

Tabanı önceden bilmiyorsanız, ancak doğru öneklere sahip olacaklarını biliyorsanız, temel olarak geçerseniz Python bunu sizin için çıkarabilir 0:

>>> int("0b11111", 0)
31
>>> int('0o37', 0)
31
>>> int('0x1f', 0)
31

Diğer Tabanlardan Ondalık Olmayan (yani Tamsayı) Değişmez Değerler

Motivasyonunuz sabit kodlu belirli değerleri açıkça temsil etmekse, temellerden dönüştürmeniz gerekmeyebilir - Python'un bunu sizin için doğru sözdizimiyle otomatik olarak yapmasına izin verebilirsiniz.

Aşağıdaki değişmez değerlerle tamsayılara otomatik dönüşüm elde etmek için apropos öneklerini kullanabilirsiniz . Bunlar Python 2 ve 3 için geçerlidir:

İkili, önek 0b

>>> 0b11111
31

Sekizlik, önek 0o

>>> 0o37
31

Onaltılık, önek 0x

>>> 0x1f
31

Bu, ikili bayraklar, koddaki dosya izinleri veya renkler için onaltılık değerler tanımlanırken yararlı olabilir - örneğin, tırnak işareti yok:

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

Belirsiz Python 2 sekizliklerini Python 3 ile uyumlu hale getirme

0 ile başlayan bir tam sayı görürseniz, Python 2'de bu (kullanımdan kaldırılmış) sekizlik sözdizimidir.

>>> 037
31

Kötü çünkü değer olması gerektiği gibi görünüyor 37. Python 3'te, şimdi bir SyntaxError:

>>> 037
  File "<stdin>", line 1
    037
      ^
SyntaxError: invalid token

Python 2 sekizliklerinizi 0oönek ile hem 2 hem de 3'te çalışan sekizliklere dönüştürün :

>>> 0o37
31

20

Soru biraz eski gibi görünüyor. Ama benzer bir şey yapan parseStr işlevini önereyim, yani tamsayı veya kayan nokta döndürür ve belirli bir ASCII dizesi bunların hiçbirine dönüştürülemezse ona dokunulmaz. Elbette kod sadece istediğinizi yapacak şekilde ayarlanabilir:

   >>> import string
   >>> parseStr = lambda x: x.isalpha() and x or x.isdigit() and \
   ...                      int(x) or x.isalnum() and x or \
   ...                      len(set(string.punctuation).intersection(x)) == 1 and \
   ...                      x.count('.') == 1 and float(x) or x
   >>> parseStr('123')
   123
   >>> parseStr('123.3')
   123.3
   >>> parseStr('3HC1')
   '3HC1'
   >>> parseStr('12.e5')
   1200000.0
   >>> parseStr('12$5')
   '12$5'
   >>> parseStr('12.2.2')
   '12.2.2'

8
1e3python'daki bir sayı, ancak kodunuza göre bir dizedir.
Cees Timmerman

16

float("545.2222") ve int(float("545.2222"))


1
Dizeniz diğer geçerli sayılar için verdiği int yerine "0" veya "0,0" olursa, bu size bir kayan nokta nesnesi verecektir.
Brian

14

Bunun için bu işlevi kullanıyorum

import ast

def parse_str(s):
   try:
      return ast.literal_eval(str(s))
   except:
      return

Dizeyi türüne dönüştürür

value = parse_str('1')  # Returns Integer
value = parse_str('1.5')  # Returns Float

parse_str(' 1')( Boşlukla birlikte) geri dönmeyeceğini lütfen Noneunutmayın 1.
musiphil

13

YAML ayrıştırıcı Eğer veri türü dize olduğunu anlamaya yardımcı olabilir. Kullanın yaml.load()ve sonra type(result)türü test etmek için kullanabilirsiniz :

>>> import yaml

>>> a = "545.2222"
>>> result = yaml.load(a)
>>> result
545.22220000000004
>>> type(result)
<type 'float'>

>>> b = "31"
>>> result = yaml.load(b)
>>> result
31
>>> type(result)
<type 'int'>

>>> c = "HI"
>>> result = yaml.load(c)
>>> result
'HI'
>>> type(result)
<type 'str'>

11
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

1
exceptOrada hiçbir şey yapmıyorsanız neden bölümünüzde yükseltin ? float () sizin için yükselecektir.
Greg0ry

1
haklısın Sanırım kopyaladım ve belirli bir istisnayı yükselttiğim bir işlevsellikten yapıştırdım. düzenleyecektir. teşekkürler
Totoro

1
Bu, bir dizeyi ayrıştırmaya ve dizenin neyi temsil ettiğine bağlı olarak ya intda döndürmeye çalışacaktır float. Ayrıştırma istisnalarını artırabilir veya [beklenmeyen davranışlara sahip olabilir] [1].
Kuzeko

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

6

Bunu düzgün yapmak için yuvarlamayı dikkate almanız gerekir.

İnt (5.1) => 5 int (5.6) => 5 - yanlış, 6 olmalı, böylece int (5.6 + 0.5) => 6

def convert(n):
    try:
        return int(n)
    except ValueError:
        return float(n + 0.5)

4
İyi bir nokta. Bu enflasyona neden olur, bu nedenle Python 3 ve diğer modern diller bankacının yuvarlamasını kullanır.
Cees Timmerman

2
Bu cevap yanlış (başlangıçta yazıldığı gibi). Bu iki olgu muddles intve float. Ve nOP istendiği gibi, bir dize olduğunda bir istisna verecektir . Belki geliyordu: Ne zaman bir intsonuç isteniyorsa, roundyüzer bitti SONRA dönüşüm olmalıdır. Eğer fonksiyon HER ZAMAN bir int döndürürse, o zaman dışarıdaki parçaya ihtiyacınız yoktur - tüm fonksiyon gövdesi olabilir int(round(float(input))). İşlev mümkünse bir int döndürürse, aksi halde bir şamandıra, javier'in orijinal çözümü doğrudur!
ToolmakerSteve

5

Kimse regex bahsetmedim şaşırdım çünkü bazen dize numaraya dökümden önce hazırlanmalı ve normalleştirilmelidir

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

kullanımı:

parseNumber('13,345')
> 13345.0

parseNumber('- 123 000')
> -123000.0

parseNumber('99999\n')
> 99999.0

ve bu arada, bir numaranız olduğunu doğrulamak için bir şey:

import numbers
def is_number(value):
    return isinstance(value, numbers.Number)
    # will work with int, float, long, Decimal

5

Python'da tahmin etmek için, dizeyi (veya yayınlamaya çalıştığınız değeri) parametre olarak geçirerek türün yapıcı işlevlerini kullanın.

Örneğin:

>>>float("23.333")
   23.333

Perde arkasında, python __float__parametrenin şamandıra temsilini döndürmesi gereken nesneler yöntemini çağırıyor . Bu, özellikle kendi türlerinizi (sınıfları kullanarak) bir __float__yöntemle tanımlayabileceğiniz için güçlüdür, böylece şamandıra (myobject) kullanılarak bir şamandıraya dökülebilir.


3

Bu düzeltilmiş bir versiyonu arasında https://stackoverflow.com/a/33017514/5973334

Bu, bir dizeyi ayrıştırmaya ve dizenin neyi temsil ettiğine bağlı olarak ya intda döndürmeye çalışacaktır float. Ayrıştırma istisnalarını artırabilir veya beklenmedik davranışlar gösterebilir .

  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

2

Dizenizi bu işleve iletin:

def string_to_number(str):
  if("." in str):
    try:
      res = float(str)
    except:
      res = str  
  elif(str.isdigit()):
    res = int(str)
  else:
    res = str
  return(res)

Ne geçtiğine bağlı olarak int, float veya string döndürür.

int olan dize

print(type(string_to_number("124")))
<class 'int'>

kayan nokta

print(type(string_to_number("12.4")))
<class 'float'>

dize olan dize

print(type(string_to_number("hello")))
<class 'str'>

kayan nokta gibi görünen dize

print(type(string_to_number("hel.lo")))
<class 'str'>

1

kullanın:

def num(s):
    try:
        for each in s:
            yield int(each)
    except ValueError:
        yield float(each)
a = num(["123.55","345","44"])
print a.next()
print a.next()

Bu benim gelebileceğim en Pitonik yol.


Jeneratör ilk yorumundan sonra durur float. try... catchblok muhtemelen içeride olmalıdır fordöngü.
musiphil

1

Onaltılık, sekizli, ikili, ondalık ve kayan nokta işlemek

Bu çözüm, sayılar için tüm dize kurallarını (bildiğim her şeyi) işleyecektir.

def to_number(n):
    ''' Convert any number representation to a number 
    This covers: float, decimal, hex, and octal numbers.
    '''

    try:
        return int(str(n), 0)
    except:
        try:
            # python 3 doesn't accept "010" as a valid octal.  You must use the
            # '0o' prefix
            return int('0o' + n, 0)
        except:
            return float(n)

Bu test senaryosu çıktısı, neden bahsettiğimi gösteriyor.

======================== CAPTURED OUTPUT =========================
to_number(3735928559)   = 3735928559 == 3735928559
to_number("0xFEEDFACE") = 4277009102 == 4277009102
to_number("0x0")        =          0 ==          0
to_number(100)          =        100 ==        100
to_number("42")         =         42 ==         42
to_number(8)            =          8 ==          8
to_number("0o20")       =         16 ==         16
to_number("020")        =         16 ==         16
to_number(3.14)         =       3.14 ==       3.14
to_number("2.72")       =       2.72 ==       2.72
to_number("1e3")        =     1000.0 ==       1000
to_number(0.001)        =      0.001 ==      0.001
to_number("0xA")        =         10 ==         10
to_number("012")        =         10 ==         10
to_number("0o12")       =         10 ==         10
to_number("0b01010")    =         10 ==         10
to_number("10")         =         10 ==         10
to_number("10.0")       =       10.0 ==         10
to_number("1e1")        =       10.0 ==         10

İşte test:

class test_to_number(unittest.TestCase):

    def test_hex(self):
        # All of the following should be converted to an integer
        #
        values = [

                 #          HEX
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (0xDEADBEEF  , 3735928559), # Hex
                ("0xFEEDFACE", 4277009102), # Hex
                ("0x0"       ,          0), # Hex

                 #        Decimals
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (100         ,        100), # Decimal
                ("42"        ,         42), # Decimal
            ]



        values += [
                 #        Octals
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (0o10        ,          8), # Octal
                ("0o20"      ,         16), # Octal
                ("020"       ,         16), # Octal
            ]


        values += [
                 #        Floats
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (3.14        ,       3.14), # Float
                ("2.72"      ,       2.72), # Float
                ("1e3"       ,       1000), # Float
                (1e-3        ,      0.001), # Float
            ]

        values += [
                 #        All ints
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                ("0xA"       ,         10), 
                ("012"       ,         10), 
                ("0o12"      ,         10), 
                ("0b01010"   ,         10), 
                ("10"        ,         10), 
                ("10.0"      ,         10), 
                ("1e1"       ,         10), 
            ]

        for _input, expected in values:
            value = to_number(_input)

            if isinstance(_input, str):
                cmd = 'to_number("{}")'.format(_input)
            else:
                cmd = 'to_number({})'.format(_input)

            print("{:23} = {:10} == {:10}".format(cmd, value, expected))
            self.assertEqual(value, expected)

0

kullanın:

>>> str_float = "545.2222"
>>> float(str_float)
545.2222
>>> type(_) # Check its type
<type 'float'>

>>> str_int = "31"
>>> int(str_int)
31
>>> type(_) # Check its type
<type 'int'>

0

Bu, sağlanan gerçek dizgenin veya gibi görünmesine bağlı olarak object(yalnızca değil str) intveya işlevini dönüştüren bir işlevdir . İkisi birlikte bir nesne daha halinde ve yöntemler kullanarak bu varsayılanfloat intfloat__float__int____float__

def conv_to_num(x, num_type='asis'):
    '''Converts an object to a number if possible.
    num_type: int, float, 'asis'
    Defaults to floating point in case of ambiguity.
    '''
    import numbers

    is_num, is_str, is_other = [False]*3

    if isinstance(x, numbers.Number):
        is_num = True
    elif isinstance(x, str):
        is_str = True

    is_other = not any([is_num, is_str])

    if is_num:
        res = x
    elif is_str:
        is_float, is_int, is_char = [False]*3
        try:
            res = float(x)
            if '.' in x:
                is_float = True
            else:
                is_int = True
        except ValueError:
            res = x
            is_char = True

    else:
        if num_type == 'asis':
            funcs = [int, float]
        else:
            funcs = [num_type]

        for func in funcs:
            try:
                res = func(x)
                break
            except TypeError:
                continue
        else:
            res = x

-1

İnt ve float yöntemlerini kullanarak bir dizeyi tamsayı ve float'a dönüştürebiliriz.

s="45.8"
print(float(s))

y='67'
print(int(y))

Bu cevap yeni bir şey eklemiyor. Örneğin, aynı bilgileri ve daha fazlasını veren bu cevaba bakınız .
Georgy

-3

eval()bu soruya çok iyi bir çözümdür. Sayının int veya float olup olmadığını kontrol etmek gerekmez, sadece karşılık gelen eşdeğeri verir. Başka yöntemler gerekiyorsa,

if '.' in string:
    print(float(string))
else:
    print(int(string))

try-hariç alternatif olarak da kullanılabilir. Dizeyi try bloğunun içindeki int değerine dönüştürmeyi deneyin. Dize kayan değer olacaksa, hariç blokta yakalanacak bir hata atar, şöyle

try:
    print(int(string))
except:
    print(float(string))

-10

İşte sorunuzun başka bir yorumu (ipucu: belirsiz). Bunun gibi bir şey arıyor olabilirsiniz:

def parseIntOrFloat( aString ):
    return eval( aString )

Bu şekilde çalışır ...

>>> parseIntOrFloat("545.2222")
545.22220000000004
>>> parseIntOrFloat("545")
545

Teorik olarak, bir enjeksiyon güvenlik açığı vardır. Dize, örneğin olabilir "import os; os.abort()". Bununla birlikte, ipin nereden geldiğine dair herhangi bir arka plan olmadan, olasılık teorik spekülasyondur. Soru belirsiz olduğu için, bu güvenlik açığının gerçekten var olup olmadığı açık değildir.


7
Girdileri% 100 güvenli olsa bile, eval()3 kat daha yavaştır try: int(s) except: float(s).
Cees Timmerman

1
Eh, evalkötü uygulama (eğer 310K üne sahip çünkü bilmesi gerekir) 'dir
U10-İleri
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.