Como saber se a string começa com um número com Python?

95

Eu tenho uma string que começa com um número (de 0-9) Eu sei que posso "ou" 10 casos de teste usando startswith () mas provavelmente há uma solução mais limpa

então ao invés de escrever

if (string.startswith('0') || string.startswith('2') ||
    string.startswith('3') || string.startswith('4') ||
    string.startswith('5') || string.startswith('6') ||
    string.startswith('7') || string.startswith('8') ||
    string.startswith('9')):
    #do something

Existe uma maneira mais inteligente / eficiente?

Ilusionista
fonte
Se a pergunta for: "Isso é muito repetitivo?", As chances são - em uma linguagem de alto nível - a resposta é "Por que, sim, com certeza é". Ser preguiçoso!
42
Você errou string.startswith('1').
MAK,
2
@Illusionist Como está escrito, sua pergunta significa que você deseja detectar as strings que começam com apenas UM dígito. Se assim for, a resposta só direito entre as seguintes, não são os que utilizam s[0]ou s[:1]Mas a solução de John Machin: if s.startswith(tuple('0123456789')). Além disso, essa solução gera erro quando acontece que s é uma sequência como uma tupla ou lista, cujos casos produzem o mesmo resultado que se fosse uma string. - Outra solução é uma regex cujo padrão é '\ d (? = \ D)', mas o uso de regex é supérfluo aqui.
eyquem de
3
Apenas sendo pedante: stringé um módulo da biblioteca padrão e provavelmente não deve ser usado como um nome de variável. docs.python.org/2/library/string.html
gak

Respostas:

177

A stringbiblioteca do Python tem isdigit()método:

string[0].isdigit()
plaes
fonte
5
O string módulo do Python2 não tem métodos e isdigité um método de stre unicodeobjetos.
John Machin,
3
@plaes: -1 por causa do acima MAIS ele trava se s == ""
John Machin
4
Veja minha resposta, que não se string[:1].isdigit()
divide
25
>>> string = '1abc'
>>> string[0].isdigit()
True
jcomeau_ictx
fonte
Eu não sou um cara do python, então talvez você possa me ajudar nisso: essa função bombará em "", onde não há string[0]?
corsiKa,
sim, com certeza vai. você pode usar (string ou 'x') [0] .isdigit () para corrigi-lo para '' ou nenhum
jcomeau_ictx
30
Você pode tentar string[:1].isdigit(), o que não deixará de lidar com uma string vazia.
Simon Callan,
2
porque essa não é minha resposta; o meu é ainda melhor no caso em que o programador deseja que uma exceção seja lançada em uma string vazia.
jcomeau_ictx
1
@jcomeau_ictx exatamente certo. nunca programe defensivamente. se a string estiver inesperadamente em branco, isso deve ocorrer em erro e não deve ser tratado automaticamente de qualquer maneira. Algumas escolas de pensamento dizem que você deve lidar com e capturar exceções que não são críticas como advertência e manter o programa funcionando. Não tenho essa mentalidade para a maioria dos casos de uso. A especificidade nas funções e no código que você está escrevendo ajuda a mitigar os casos extremos em que você precisaria codificar defensivamente com mais frequência.
jamescampbell
10

às vezes, você pode usar regex

>>> import re
>>> re.search('^\s*[0-9]',"0abc")
<_sre.SRE_Match object at 0xb7722fa8>
kurumi
fonte
exagero! Por que usar fogo quando você pode fazer isso nos bultins
Jakob Bowyer,
1
@JakobBowyer Pelo menos, é bom saber disso! Mesmo que neste caso, sim, regexes SÃO um exagero se alguns builtins podem fazer o mesmo.
jeromej
8

Seu código não funcionará; você precisa em orvez de ||.

Experimentar

'0' <= strg[:1] <= '9'

ou

strg[:1] in '0123456789'

ou, se você é realmente louco por startswith,

strg.startswith(('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'))
John Machin
fonte
Eu teria votado contra você se houvesse apenas a solução com startswith (uma tupla) . Mas as soluções com strg[:1]têm dois inconvenientes: não geram um erro se s for uma lista de strings e produzem True se a string começar com VÁRIOS dígitos.
eyquem de
@eyquem eles produzem True se a string começar com VÁRIOS dígitos. Então? Outras respostas não verificam isso, porque não era um requisito que ele tivesse que verificar se os outros caracteres não eram numéricos.
Rob Grant,
Eu sou louco por isso startswithe implementei dessa forma em meu código. Obrigado.
jamescampbell
Mais uma partida com possibilidade ...startswith(tuple(str(i) for i in range(10)))
Jérôme
6

É surpreendente que depois de tanto tempo ainda falte a melhor resposta.

A desvantagem das outras respostas é usar [0]para selecionar o primeiro caractere, mas, como observado, isso quebra na string vazia.

Usar o seguinte contorna esse problema e, na minha opinião, fornece a sintaxe mais bonita e legível das opções que temos. Também não importa / incomoda com regex):

>>> string = '1abc'
>>> string[:1].isdigit()
True

>>> string = ''
>>> string[:1].isdigit()
False
PascalVKooten
fonte
4

Este trecho de código:

for s in ("fukushima", "123 is a number", ""):
    print s.ljust(20),  s[0].isdigit() if s else False

imprime o seguinte:

fukushima            False
123 is a number      True
                     False
eyquem
fonte
4
Isso é feio. Use s[:1].isdigit()ous and s[0].isdigit()
John Machin de
1
@John Machin O que você quer dizer com 'feio'? Ilegível ? Não acho suas proposições aqui acima mais legíveis. s and s[0].isdigit()é ainda menos legível na minha opinião. Pessoalmente, gosto da construção ... if ... else ... Levando em consideração sua observação, gostaria apenas de melhorá-la assim:s[0].isdigit() if s!="" else False
eyquem
2

Você também pode usar try...except:

try:
    int(string[0])
    # do your stuff
except:
    pass # or do your stuff
One Face
fonte
1

Aqui estão minhas "respostas" (tentando ser único aqui, eu realmente não recomendo para este caso em particular :-)

Usando ord () eo a <= b <= cformulário especial :

//starts_with_digit = ord('0') <= ord(mystring[0]) <= ord('9')
//I was thinking too much in C. Strings are perfectly comparable.
starts_with_digit = '0' <= mystring[0] <= '9'

(Isso a <= b <= c, como a < b < c, é uma construção especial do Python e é bem legal: compare 1 < 2 < 3(verdadeiro) e 1 < 3 < 2(falso) e (1 < 3) < 2(verdadeiro). Não é assim que funciona na maioria das outras linguagens.)

Usando uma expressão regular :

import re
//starts_with_digit = re.match(r"^\d", mystring) is not None
//re.match is already anchored
starts_with_digit = re.match(r"\d", mystring) is not None

fonte
1
(1) Perder o ord()(2) Perder o ^na regex.
John Machin,
0

Você pode usar expressões regulares .

Você pode detectar dígitos usando:

if(re.search([0-9], yourstring[:1])):
#do something

O par [0-9] corresponde a qualquer dígito, e sua string [: 1] corresponde ao primeiro caractere de sua string

Tovi7
fonte
-2

Use Expressões regulares , se você for estender de alguma forma a funcionalidade do método.

Ilya Smagin
fonte
-5

Experimente isto:

if string[0] in range(10):
bradley.ayers
fonte
Isso não funciona de jeito nenhum. range(10)produz uma lista de inteiros, enquanto string[0]é uma string de comprimento 1.
Petri Lehtinen,
1
Isso não funciona; os tipos não combinam. Mas: if string[0] in map(str,range(10))funciona
phynfo,