Main Content

Python varables - checking existance, and call by name or by value?

Archive - Originally posted on "The Horse's Mouth" - 2013-08-27 15:48:56 - Graham Ellis

A couple of good questions from a recent delegate...

Q. How do I check for the existance of a variable in Python?

A. Reference it and see if an exception is thrown. Here's an example in which I create a variable only if my program is run with command line parameters:

  import sys
  if len(sys.argv) > 1:
    thing = "Called with parameters"
  
  try:
    thing
    have = "something"
  except:
    have = "nothing"
  print have


And running that gives me:

  WomanWithCat:twcrp grahamellis$ python pval qweqeqwe
  something
  WomanWithCat:twcrp grahamellis$ python pval
  nothing
  WomanWithCat:twcrp grahamellis$


If you don't like exceptions (!), you could always try the dir function which returns you symbol table contents...

  if "thing" in dir():
    print "have"
  else:
    print "have not"


The question concerns me slightly - as it's usually good coding practise to know what variables you have, and to clean up optional temporary ones at the closure of a scope.

Q. Python subroutine calls, are they "by value" or "by reference" or both?

A. They are called by reference. Which means that the address at which a variable id held is passed into the method / function (they're not really called "subroutines") and it's very efficient in that way. It also means that if you make changes within the variable's contents inside the method, you'll also change what the reference outside the function considers to be a value. Consider the internal name to be an alternative name or alias for the same thing.

  def employ(team,add):
    team.append(add)
  def unemploy(team, subtract):
    team.remove(subtract)
  
  people = ["Amanda","Bob","Chris","Deborah"]
  employ(people,"Eric")
  unemploy(people,"Bob")
  print people


And that runs as follows - with the changes show within the methods reflcted outside

  WomanWithCat:twcrp grahamellis$ python pin
  ['Amanda', 'Chris', 'Deborah', 'Eric']
  WomanWithCat:twcrp grahamellis$


There is, however, a further issue to consider - my correspondent writes:

"Here I am getting confused, looks like list is by-reference and integer is by-value. What rule is Python following?"

It's by REFERENCE. However, some variables (tuples and integers for example) are immutable and that means that when their value is altered a new variable / reference name is created. And if that's just under the alias name,it leaves the original name pointing to the original value, thus giving the appearance of call be value.

You can see how that works using Python's id function ...

  def stepup(thisval):
    print id(thisval)
    thisval += 1
    print id(thisval)
  
  lucky = 7
  print id(lucky)
  print lucky
  stepup(lucky)
  print id(lucky)
  print lucky


Which reports a brand new object after the += operation ... but ONLY at that point:

  4352717096
  7
  4352717096
  4352717072
  4352717096
  7


Using a list with a single member, you can get the opposite behaviour:

  4499263856
  [7]
  4499263856
  4499263856
  4499263856
  [8]