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)
Mark Harrison
fonte
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)
Tríptico
fonte
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)
SilentGhost
fonte
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.

dorvak
fonte
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) # -> ''
Vinay Sajip
fonte
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!

Alex Martelli
fonte
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
14
def xstr(s):
   return s or ""
Krystian Cybulski
fonte
4
Isso retorna ''para 0, [], {}, Falsee falso-like valores, que não é o que o cartaz pediu.
StvnW
1
basta colocar str [...] em torno de s: def xstr(s): return str(s) or ""
Federico Simonetta 24/12
8

Maneira funcional (one-liner)

xstr = lambda s: '' if s is None else s
Dario
fonte
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
8

Uma linha simples para fazer isso com base em algumas das outras respostas:

s = (lambda v: v or '')(a) + (lambda v: v or '')(b)

ou mesmo apenas:

s = (a or '') + (b or '')
Willem van Ketwich
fonte
Por que mencionar (lambda v: v or '')?
Tvde1
Por que não? 2 dicas pelo preço de 1! Will
Willem van Ketwich 06/02/19
1
Esteja ciente de que a Falselista vazia também será alterada para ''.
Nik O'Lai 20/09/19
mesmo para 0, etc.
Walter Tross
6
def xstr(s):
    return {None:''}.get(s, s)
tobidope
fonte
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.

Radtek
fonte
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 ''
Peter Ericson
fonte
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)
maciek
fonte
1
def xstr(s):
    return s if s else ''

s = "%s%s" % (xstr(a), xstr(b))
phillc
fonte
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.

Sonar Pralhad Narsinh
fonte
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 '')
sharjeel
fonte
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}"
user781486
fonte
1
Isso está errado e retorna a string, 'None'se sestiver None.
Lawrence