Python: a maneira mais idiomática de converter None em string vazia?


156

Qual é a maneira mais idiomática de fazer o seguinte?

def xstr(s):
    if s is None:
        return ''
    else:
        return s

s = xstr(a) + xstr(b)

atualização: estou incorporando a sugestão de Tryptich para usar str (s), o que faz essa rotina funcionar para outros tipos além de strings. Estou muito impressionado com a sugestão lambda de Vinay Sajip, mas quero manter meu código relativamente simples.

def xstr(s):
    if s is None:
        return ''
    else:
        return str(s)

7
Eu gosto da sua sintaxe original. Eu acho que já é bem claro e fácil de ler.
GuiSim 23/06/09

1
@GuiSim: Eu poderia ser tendenciosa, mas a minha resposta lê quase como uma sentença normal de Inglês ...
SilentGhost

1
"Se s for Nenhum, retorne uma string vazia; caso contrário, retorne [string de] s." O código da pergunta também parece uma frase em inglês normal.

a) Se a string sveio de uma pesquisa de ditado onde a chave não foi encontrada, usedict.get(key, '')
smci 27/07/1919

b) Se você deseja apenas essa conversão de string para formatação de saída (por exemplo, para impressão), é possível fazer diretamente '... {}'. format (dict.get (1)) `
smci

Respostas:


94

Se você realmente deseja que sua função se comporte como a str()incorporada, mas retorne uma sequência vazia quando o argumento for Nenhum, faça o seguinte:

def xstr(s):
    if s is None:
        return ''
    return str(s)

Estou mantendo o resto, mas obrigado pela dica str (s) para que vários tipos possam ser manipulados. legais!
Mark Harrison

11
Ou simplesmentexstr = lambda s: '' if s is None else str(s)
Michael Mior

2
Eu amo digitar em if not s:vez deif s is None
guneysus

6
@ guneysus Eles não são os mesmos: not False == Truemas False is None == False.
Lynn

Obrigado @Lynn, você está certo. Eu percebi minha culpa. Mas eu sei (ou assumo) ssempre um tipo str / unicode ou None. Sim, Falseé um valor, mas eu prefiro dessa forma que salva o meu teclado e os olhos;)
guneysus

143
def xstr(s):
    return '' if s is None else str(s)

3
Essa sintaxe foi introduzida no 2.5; para versões anteriores do Python, você pode usar return s is not None and s or ''.
11459 Ben Blank

8
Eu dar a volta a enfatizar o caso mais commen: retorno s Se s não é nenhuma outra ""
Ber

5
@ Ber: Gostaria de mantê-lo como está, para evitar um duplo negativo.
Nikhil Chelliah

8
Este é um bom exemplo de como .. and .. or ..falha e por que se-mais é preferido. Existem dois erros sutis s is not None and s or ''.

1
return '' if not s else str(s)
Iqbal

108

Provavelmente o menor seria str(s or '')

Porque None é False, e "x ou y" retorna y se x for falso. Consulte Operadores booleanos para obter uma explicação detalhada. É curto, mas não muito explícito.


1
isso é ótimo, obrigado! Nunca pensei em usar oreste caminho #
user25064

15
Isso não funciona se sfor 0, False, ou qualquer valor Falsas
wisbucky

4
Bem, isso não é mencionado no requisito da operação, então não entendo seu ponto aqui.
dorvak 10/09/2015

2
@dorvak O OP é bastante explícito sobre o requisito de que a saída seja ''iff s is None. Todas as outras entradas devem retornar s(ou str(s)na solicitação revisada).
StvnW

2
@fortea: isso não vai funcionar. Se sé None, o resultado xstr()deve ser uma cadeia vazia, mas str(None)dá a corda "None", que é o que é devolvido (uma vez que a corda "None"não é um valor Falsas.
dreamlax

97

Se você souber que o valor sempre será uma sequência ou Nenhum:

xstr = lambda s: s or ""

print xstr("a") + xstr("b") # -> 'ab'
print xstr("a") + xstr(None) # -> 'a'
print xstr(None) + xstr("b") # -> 'b'
print xstr(None) + xstr(None) # -> ''

1
de longe o mais pitônico. Usa o fato de o python tratar None, uma lista vazia, uma string vazia, 0, etc. como falsa. Também usa o fato de que a instrução ou retorna o primeiro elemento que é verdadeiro ou o último elemento fornecido aos ou (ou grupos de ors). Além disso, isso usa funções lambda. Eu daria a você +10, mas obviamente isso não me deixará.
Matt

11
Isto irá converter 0 e False (e qualquer outra coisa que avalia a falsa quando passou para bool ())
Arkady

9
Não acho que seja "de longe o mais pitônico". É um idioma comum em outras linguagens, e não acho errado usá-lo em Python, mas expressões condicionais foram introduzidas precisamente para evitar truques como esse.
Roberto Bonvallet

2
Isso faz com que [], {}etc. dê o mesmo resultado que None, o que não é desejado. xstr(False), em particular, deve ser em "False"vez de "". Abusar lambdas é um mau exemplo, use def xstr(s): return s or ""ir e você deseja manter tudo em uma linha.

5
Observe que qualifiquei minha resposta desde o início com "Se você sabe que o valor sempre será uma string ou Nenhum".
Vinay Sajip

59

return s or '' funcionará bem para o seu problema declarado!


4
Vale notar que isso vai dar um resultado diferente para quando s é Falso ou 0 (que não é a questão string original, mas o atualizado.)
Oddthinking

@Oddthinking s = Falseou s = 0seria mais provável ser um caso extremo em seu uso, e pode ser facilmente atenuado por escrevê-lo comoreturn str(s or '')
Willem van Ketwich

@WillemvanKetwich: Isso tem exatamente o mesmo problema: s (False) deve retornar 'False', não ''. s (0) deve retornar '0', não ''. Da mesma forma para um objeto que define __bool__ ou __nonzero__.
Oddthinking

@ Pensando bem, entendo o seu ponto. De qualquer forma, se for usado exclusivamente para objetos de string, como na pergunta do OP, não deve ser um problema.
Willem van Ketwich

@WillemvanKetwich: Ter um olhar para a questão atualizado e a ressalva no meu comentário - este foi coberto,
Oddthinking


8

Maneira funcional (one-liner)

xstr = lambda s: '' if s is None else s

1
"def xstr (s): O Retorno '' se s há outro s" é um on-liner também, python não é tão rigoroso com espaços em branco depois de tudo
SilentGhost

2
Não é nenhum one-liner real, é apenas escrito em uma linha g
Dario

1
em que sentido não é um onliner real? verifique seu intérprete - não é um erro de sintaxe. para todos os efeitos, é muito real que lambda ^ _ ^ #
SilentGhost

2
PEP 8 espécies que você deve usar def em vez de atribuir lambda a uma variável. A única vantagem real do lambda é que você pode escrever como parte da expressão (passando para outra função, por exemplo) e essa vantagem é perdida em códigos como este. Eu costumava fazer isso também, até perceber que def pode ser escrito em uma linha e, em seguida, o PEP 8 me mostrou o caminho a seguir. SEMPRE siga os deuses python.
26514 Guy


6
def xstr(s):
    return {None:''}.get(s, s)

Eu acho que é bastante pitônico - e quanto a este: "xstr = lambda s: {None: ''.. Get (s, s)" - reduz a coisa toda a uma linha.
21409 Juergen

14
Desnecessariamente lento (construção e pesquisa de ditado extra) e mais difícil de ler. Muito antitônico.
Triptych

Você está certo. É bastante perlish, mas evita um salto condicional no bytecode python.
Tobidope

4
A chamada da função get () implica pelo menos um salto condicional adicional.
Triptych

1
Eu não seria capaz de dizer o que isso deve fazer sem saber a pergunta ou olhar para cima get.
Dario

5

Eu uso a função max:

max(None, '')  #Returns blank
max("Hello",'') #Returns Hello

Funciona como um encanto;) Basta colocar sua string no primeiro parâmetro da função.


5
Isso funciona porque 'str'> 'NoneType' e é específico do CPython. No manual : "Objetos de tipos diferentes, exceto números, são ordenados por seus nomes de tipo". Além disso, isso não funcionará no Python 3000, pois a comparação entre tipos não é mais permitida (TypeError: tipos desordenados: str ()> NoneType ()). Veja Como o Python compara string e int?
Plok

É bom saber obrigado, por isso não é uma boa ideia avançar com o código compatível com python 3.x.
Radtek 04/07

4

Variação acima, se você precisar ser compatível com o Python 2.4

xstr = lambda s: s is not None and s or ''

2

Se se trata de formatar seqüências de caracteres, você pode fazer o seguinte:

from string import Formatter

class NoneAsEmptyFormatter(Formatter):
    def get_value(self, key, args, kwargs):
        v = super().get_value(key, args, kwargs)
        return '' if v is None else v

fmt = NoneAsEmptyFormatter()
s = fmt.format('{}{}', a, b)

1
def xstr(s):
    return s if s else ''

s = "%s%s" % (xstr(a), xstr(b))

5
Isso retornará uma string vazia para todos os valores falsos, que não é o que o pôster solicitou.
Triptych

1

Sempre podemos evitar a conversão de tipos nos cenários explicados abaixo.

customer = "John"
name = str(customer)
if name is None
   print "Name is blank"
else: 
   print "Customer name : " + name

No exemplo acima, no caso de o valor da variável do cliente ser None, ele também é convertido enquanto é atribuído a 'name'. A comparação na cláusula 'if' sempre falhará.

customer = "John" # even though its None still it will work properly.
name = customer
if name is None
   print "Name is blank"
else: 
   print "Customer name : " + str(name)

O exemplo acima funcionará corretamente. Tais cenários são muito comuns quando valores estão sendo buscados a partir de URL, JSON ou XML ou mesmo valores precisam de conversão de tipo adicional para qualquer manipulação.


0

Use a avaliação de curto-circuito:

s = a or '' + b or ''

Como + não é uma operação muito boa em strings, use melhor as strings de formato:

s = "%s%s" % (a or '', b or '')

2
Isso também converterá 'a' em cadeias vazias para todos os valores do tipo falso, não apenas Nenhum. Por exemplo, tuplas, listas e ditados vazios serão convertidos em cadeias vazias, o que não é o que o OP especificou.
Triptych

+é um operador perfeitamente bom para duas strings. É quando você tenta usá-lo para juntar-se a dezenas que tem problemas. Para dois, provavelmente será mais rápido que outras opções; de qualquer maneira, está no barulho.
kquinn

+1 para mim porque é exatamente isso que preciso no meu caso: lambda ou function para substituir um único operador ( or) parece um pouco exagerado para mim ... não tenho casos de outros valores falsamente - str ou None. Que não seja o comentário sobre o +operador, que pode depender de cenário específico e pode precisar de benchmarking, esta resposta não não merecem um -1
urbana

-3

Use a string F se você estiver usando o python v3.7

xstr = F"{s}"

1
Isso está errado e retorna a string, 'None'se sestiver None.
Lawrence
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.