-1

Is the following considered bad practice:

var = var if 'var' in globals() else None    

In other words, if there is an if statement that defines a variable, and I may need to access that variable later, to use a construction such as the above, instead of having to define the variable as None before the if statement.

Why or why not would the above construction be acceptable?

An example would be like this:

if process == 'yes':
    # 100 lines of code
    obj = {...}


return Response(obj)
David542
  • 104,438
  • 178
  • 489
  • 842
  • 1
    Wouldn’t you use a try/except with `NameError`? Anyhow, I don’t think it signals a good piece of code if there is a doubt in whether variables are defined. I would expect them to be defined, but with a value of, say, `None`. – N Chauhan Dec 31 '19 at 23:42
  • Could you give an example use case? I can't think of a situation where you couldn't catch `NameError` instead of this. – wjandrea Dec 31 '19 at 23:45
  • See my [answer](https://stackoverflow.com/questions/3930188/how-to-convert-nonetype-to-int-or-string/3931746#3931746) to a question that addresses this subject. – martineau Dec 31 '19 at 23:47
  • 2
    I can't really think of a good reason why you'd ever have to guess if a variable is defined. What is the use case, exactly? To me, this is major code smell. – juanpa.arrivillaga Dec 31 '19 at 23:51
  • FWIW Pyflakes gives an error: `E0602 undefined name 'var'`. – wjandrea Dec 31 '19 at 23:56
  • 1
    "...instead of having to define the variable as None before the if statement." Wouldn't that be much cleaner and simpler, though? – tobias_k Jan 01 '20 at 00:08

2 Answers2

3

Yes it is bad practice. Both by using globals() or except NameError. Instead simply define all the variables you will use. There is never the need to either have them defined or not.

In your example:

obj = None

if process == 'yes':
    # 100 lines of code
    obj = {...}

#maybe log a warning in case obj is None still. or handle it in the caller
return Response(obj)
antont
  • 2,676
  • 1
  • 19
  • 21
0

Yes it's bad practice. Regardless of whether it's practical, it mixes scopes, which is confusing. You check if var is defined in the global scope but then get its value from the current scope, whether that's global or not. For example:

def func():
    var = 'Local'
    var = var if 'var' in globals() else None
    print(var)

func()  # -> None
var = 'Global'
func()  # -> Local

If you want to always look up var in the global scope, use dict.get with a default:

var = globals().get('var', None)

If you want to always look up var in the current scope, use a try-except catching a NameError like in Reblochon Masque's answer:

try:
    var = var
except NameError:
    var = None
wjandrea
  • 28,235
  • 9
  • 60
  • 81