Em C #, há um operador de coalescência nula (escrito como ??
) que permite uma verificação nula fácil (curta) durante a atribuição:
string s = null;
var other = s ?? "some default value";
Existe um equivalente python?
Eu sei que posso fazer:
s = None
other = s if s else "some default value"
Mas existe uma maneira ainda mais curta (onde eu não preciso repetir s
)?
python
null-coalescing-operator
Klaus Byskov Pedersen
fonte
fonte
??
operador é proposto como PEP 505 .Respostas:
Ok, deve ser esclarecido como o
or
operador funciona. É um operador booleano, portanto, funciona em um contexto booleano. Se os valores não forem booleanos, eles serão convertidos em booleano para os propósitos do operador.Observe que o
or
operador não retorna apenasTrue
ouFalse
. Em vez disso, ele retornará o primeiro operando se o primeiro operando for avaliado como verdadeiro e retorna o segundo operando se o primeiro operando for avaliado como falso.Nesse caso, a expressão
x or y
retornaráx
se forTrue
ou for avaliada como true quando convertida em booleana. Caso contrário, ele retornaráy
. Na maioria dos casos, isso servirá para o mesmo objetivo do operador coalescente nulo de C♯, mas lembre-se:Se você usar sua variável
s
para armazenar algo que seja uma referência à instância de uma classe ouNone
(desde que sua classe não defina membros__nonzero__()
e__len__()
), é seguro usar a mesma semântica que o operador de coalescência nula.De fato, pode até ser útil ter esse efeito colateral do Python. Como você sabe quais valores são avaliados como falsos, é possível usá-lo para acionar o valor padrão sem usar
None
especificamente (um objeto de erro, por exemplo).Em alguns idiomas, esse comportamento é chamado de operador Elvis .
fonte
s
for um valor válido, mas não for verdade? (Eu não sei Python, então eu não tenho certeza se o conceito de 'truthy' se aplica.)None
e os contêineres vazios (incluindo cadeias) são considerados falsos, além da constanteFalse
. Quase todo o resto é considerado verdadeiro. Eu diria que o principal perigo aqui seria que você obteria um valor verdadeiro, mas sem string, mas isso não será um problema em alguns programas.datetime.time(0)
também era falso!Estritamente,
Caso contrário,
s = False
se tornará"default value"
, o que pode não ser o que foi planejado.Se você quiser tornar isso mais curto, tente:
fonte
Consider x()?.y()?.z()
Aqui está uma função que retornará o primeiro argumento que não é
None
:reduce()
pode desnecessariamente repetir todos os argumentos, mesmo que o primeiro argumento não sejaNone
, então você também pode usar esta versão:fonte
def coalesce(*arg): return next((a for a in arg if a is not None), None)
faz o mesmo que o seu último exemplo em uma linha.Consider x()?.y()?.z()
Sei que isso é respondido, mas há outra opção quando você está lidando com objetos.
Se você tiver um objeto que possa ser:
Você pode usar:
Gostar:
Ao adicionar
{}
como valor padrão, se "name" estiver ausente, um objeto vazio será retornado e passado para a próxima obtenção. Isso é semelhante à navegação segura com segurança nula em C #, como seriaobj?.name?.first
.fonte
.get
, isso só funciona para dict-como objetosgetattr()
também.get
on dict não usa o parâmetro padrão se o valor for Nenhum, mas usa o parâmetro padrão se o valor não existir porque a chave não está no dict.{'a': None}.get('a', 'I do not want None')
ainda lhe daráNone
como resultado.Além da resposta de Juliano sobre o comportamento de "ou": é "rápido"
Às vezes, pode ser um atalho útil para coisas como
fonte
Adicionalmente à resposta do @Bothwells (que eu prefiro) para valores únicos, a fim de verificar de forma nula os valores de retorno da função, você pode usar o novo walrus-operator (desde python3.8):
Portanto, a
test
função não precisa ser avaliada duas vezes (como ema = 2 if test() is None else test()
)fonte
Caso você precise aninhar mais de uma operação coalescente nula, como:
model?.data()?.first()
Este não é um problema facilmente resolvido
or
. Também não pode ser resolvido com o.get()
que requer um tipo de dicionário ou similar (e não pode ser aninhado de qualquer maneira) ougetattr()
que gerará uma exceção quando NoneType não tiver o atributoO pip relevante que considera a adição de coalescência nula ao idioma é PEP 505 e a discussão relevante para o documento está no segmento python-ideas .
fonte
Em relação às respostas de @Hugh Bothwell, @mortehu e @glglgl.
Conjunto de dados de configuração para teste
Definir implementações
Faça a função de teste
Resultados no mac i7 @ 2.7Ghz usando python 2.7
Claramente o
not_none
função responde à pergunta do OP corretamente e lida com o problema de "falsidade". É também o mais rápido e fácil de ler. Se aplicar a lógica em muitos lugares, é claramente o melhor caminho a percorrer.Se você tiver um problema em que deseja encontrar o 1º valor não nulo em uma iterável, a resposta do @ mortehu é o caminho a percorrer. Mas é uma solução para um problema diferente do OP, embora possa lidar parcialmente com esse caso. Não pode levar um AND iterável e um valor padrão. O último argumento seria o valor padrão retornado, mas você não passaria um iterável nesse caso, assim como não está explícito que o último argumento seja o valor padrão.
Você poderia fazer isso abaixo, mas eu ainda usaria
not_null
para o caso de uso de valor único.fonte
Para aqueles como eu, que tropeçamos aqui, procurando uma solução viável para esse problema, quando a variável pode ser indefinida, o mais próximo que eu chego é:
Observe que uma string é necessária ao fazer check-in em globais, mas depois a variável real é usada ao verificar o valor.
Mais sobre a existência de variáveis: Como verifico se existe uma variável?
fonte
(variablename or False) == True
é o mesmo quevariablename == True
se você não conseguir encontrar o nome no dicionário, ele retornará o valor padrão; se o nome existir, ele adicionará qualquer valor existente com 1.
espero que isso possa ajudar
fonte
As duas funções abaixo são muito úteis para lidar com muitos casos de teste variáveis.
fonte