Como verifico se existe uma variável?

954

Quero verificar se existe uma variável. Agora estou fazendo algo assim:

try:
   myVar
except NameError:
   # Do something.

Existem outras maneiras, sem exceções?

Max Frai
fonte
15
O que há de errado com a exceção?
5609 S.Lott
10
@ S.Lott: se myVaré algo realmente complicado, que leva muito tempo para produzir / avaliar, não seria mais trylento?
dbliss
3
@bliss: É uma variável. Além de alguns casos realmente estranhos, se você está fazendo algo louco execou metaclasses, não vai ser caro.
User2357112 suporta Monica
Uma resposta mais completa: stackoverflow.com/a/1592578/1661797
nickboldt

Respostas:

1628

Para verificar a existência de uma variável local:

if 'myVar' in locals():
  # myVar exists.

Para verificar a existência de uma variável global:

if 'myVar' in globals():
  # myVar exists.

Para verificar se um objeto tem um atributo:

if hasattr(obj, 'attr_name'):
  # obj.attr_name exists.
Ayman Hourieh
fonte
29
Ok, e como posso verificar o atributo existente na classe?
Max Frai
7
e como você transforma o nome da variável que possivelmente não existe em uma string?
SilentGhost
15
Mas o OP está digitando o código, eles podem digitar 'myVar' em vez de myVar. Se o nome da variável não for conhecido quando o código for gravado, ele será armazenado em uma variável de sequência no tempo de execução, e a verificação que eu publiquei também funcionará.
Ayman Hourieh
8
Também existem variáveis ​​internas e, se você tiver funções aninhadas, variáveis ​​em escopos externos. Se você deseja verificar todos eles, provavelmente é melhor acionar, NameErrorafinal.
precisa
14
Gostei mais do if hasattr(obj, 'attr_name'):que funciona para as aulas também: ieif hasattr(self, 'attr_name'):
Ron Kalian 30/10
118

O uso de variáveis ​​que ainda não foram definidas ou definidas (implícita ou explicitamente) é quase sempre uma coisa ruim em qualquer idioma, pois geralmente indica que a lógica do programa não foi pensada adequadamente e provavelmente resultará em em comportamento imprevisível.

Se você precisar fazer isso no Python, o truque a seguir, semelhante ao seu, garantirá que uma variável tenha algum valor antes do uso:

try:
    myVar
except NameError:
    myVar = None

# Now you're free to use myVar without Python complaining.

No entanto, ainda não estou convencido de que seja uma boa ideia - na minha opinião, você deve tentar refatorar seu código para que essa situação não ocorra.

paxdiablo
fonte
8
Talvez seja uma variável dependente, e de acordo com a versão / plataforma que ela pode ou não existir, e não há outra maneira de saber qual é a versão.
WhyNotHugo
35
As variáveis ​​de estado não existem antes de serem atribuídas - se você desenhar uma linha da posição anterior para a posição atual e definir anterior = atual, isso não significa que você "não conhece suas variáveis" na primeira chamada. E escrever uma linha extra de código para inicializar previous = null fora da rotina de desenho não significa que você "conhece suas variáveis" melhor.
Dave
4
O que quero dizer é que um bloco "if last: draw (last, current); last = current" é fácil de entender e não é uma programação ruim. Adicionar um "try / except" para verificar a existência de "last" antes de poder testá-lo prejudica a legibilidade desse código.
Dave
23
"O uso de variáveis ​​que não foram definidas é realmente uma coisa ruim em qualquer idioma" Poupe-me o discurso condescendente. Alguns de nós usam o Python para scripts simples de matemática ou estatística usando IDEs como o Spyder, que funcionam como o Matlab. Às vezes, faz sentido nesses ambientes permitir que o usuário defina variáveis ​​no console global e verifique se não estão declaradas no script, como ao fazer matemática no Matlab.
Ricardo Cruz
15
@Ricardo, talvez, ao invés de assumir a sua condescendência, você pode querer, pelo menos, considerar a possibilidade de que ele é apenas um bom conselho de alguém que pode ser mais bem :-) Ou você consideraria igualmente condescendente se eu desaconselhadas uso irrestrito da Global variáveis, código espaguete, objetos divinos, liberando código não testado ou escrevendo sistemas operacionais em COBOL? Minha resposta afirmou por que eu achava que era uma péssima idéia (e não havia nada na pergunta indicando por que o OP achava necessário), mas ainda fornecia uma maneira de evitar que eles realmente quisessem fazê-lo.
precisa
52

Uma maneira simples é inicializá-lo dizendo primeiro myVar = None

Depois, mais tarde:

if myVar is not None:
    # Do something
Chinedum Ukejianya
fonte
2
Há muito a ser melhorado nesta resposta. Em vez disso - Uma maneira simples é declará-lo primeiro. myVar = none # do stuff... if not myVar: # give myVar a value myVar = 'something'
precisa
i como um presente muito porque eu definir as coisas para Nenhum nas minhas exceptdeclarações
HashRocketSyntax
por que não algo como: if myVar: # Do something Isso evita a necessidade de ler uma dupla negativa
jjisnow
@jjisnow Porque você deseja que essa condição seja verdadeira, mesmo que myVarseja uma lista vazia, zero, string vazia etc.
Gabriel
7
@jjisnow if myVar: # Do somethingjoga NameErrorem python3 se myVar não é declarado
Agile Feijão
25

Usar try / except é a melhor maneira de testar a existência de uma variável. Mas há quase certamente uma maneira melhor de fazer o que você está fazendo do que definir / testar variáveis ​​globais.

Por exemplo, se você deseja inicializar uma variável no nível do módulo na primeira vez que chama alguma função, é melhor usar um código como este:

my_variable = None

def InitMyVariable():
  global my_variable
  if my_variable is None:
    my_variable = ...

fonte
2
Eu tento não usar isso, porque polui o espaço para nome global. Uma maneira de evitar isso é transformar a função em uma classe, com my_variable como variável de classe, e definir a chamada como o corpo da função existente, mas isso é uma tarefa difícil de codificar e abre várias outras questões. Eu prefiro usar atributos de função, veja abaixo.
samwyse
17

para objetos / módulos, você também pode

'var' in dir(obj)

Por exemplo,

>>> class Something(object):
...     pass
...
>>> c = Something()
>>> c.a = 1
>>> 'a' in dir(c)
True
>>> 'b' in dir(c)
False
Wyrmwood
fonte
11

Assumirei que o teste será usado em uma função, semelhante à resposta do usuário97370 . Não gosto dessa resposta porque polui o espaço para nome global. Uma maneira de corrigi-lo é usar uma classe:

class InitMyVariable(object):
  my_variable = None

def __call__(self):
  if self.my_variable is None:
   self.my_variable = ...

Eu não gosto disso, porque complica o código e abre perguntas como: isso deve confirmar o padrão de programação Singleton? Felizmente, o Python permitiu que as funções tivessem atributos por um tempo, o que nos fornece esta solução simples:

def InitMyVariable():
  if InitMyVariable.my_variable is None:
    InitMyVariable.my_variable = ...
InitMyVariable.my_variable = None
samwyse
fonte
9

catché chamado exceptem Python. Fora isso, tudo bem para casos simples. Existe o AttributeErrorque pode ser usado para verificar se um objeto tem um atributo.

SilentGhost
fonte
5

Uma maneira que geralmente funciona bem para lidar com esse tipo de situação é não verificar explicitamente se a variável existe, mas seguir em frente e agrupar o primeiro uso da variável possivelmente inexistente em uma tentativa / exceto NameError:

# Search for entry.
for x in y:
  if x == 3:
    found = x

# Work with found entry.
try:
  print('Found: {0}'.format(found))
except NameError:
  print('Not found')
else:
  # Handle rest of Found case here
  ...
Roger Dahl
fonte
3

Eu criei uma função personalizada.

def exists(var):
     var_exists = var in locals() or var in globals()
     return var_exists

Em seguida, chame a função da seguinte maneira substituindo variable_namepela variável que você deseja verificar:

exists("variable_name")

Retornará TrueouFalse

Abhishek R
fonte
2
Não, isso não vai funcionar. locals()é ... err ... local para a função exists😅
bgusach
1
1) A função locals () é local. 2) Por que a atribuição extra de var_exists?
Dave