-1

This doesn't work: (global name 'a' is not defined)

if True:
  a = 3
else:
  a = 4
print a

This works:

class A:
  def f(self):
    if True:
      a = 3
    else:
      a = 4
    print a

A().f()

This doesn't work: (global name 'a' is not defined)

class A:
  def __init__(self):
    a = 3
  def f(self):
    print a

A().f()

Why is it working in one case and not in another ? I thought that if it works in case (2) then it is because a gets in the class context, but this doesn't make it work in (3) I saw other discussions but I don't understand everything that is said and cases vary a bit.

EDIT:

example 1 does NOT work, at least in a python 2.7 interpreter. This is why it examples 1 and 2 are contradictory

Thomas
  • 8,306
  • 8
  • 53
  • 92
  • 2
    The first example **does** work. `a` is always defined. – Martijn Pieters Jan 14 '14 at 11:35
  • 1
    In your last example, `a` is a local variable in `__init__`. Local variables in functions are not visible outside of the function scope. It doesn't matter that both `f` and `__init__` are methods on the same class, they don't share their local namespaces. – Martijn Pieters Jan 14 '14 at 11:37
  • 1
    @MartijnPieters First example does not work on my machine. I am using the interpreter, if it makes a difference – Thomas Jan 14 '14 at 13:21
  • 1
    Of course example 1 works, in a Python 2.7 interpreter and everywhere else. There must be a different error (`==` instead of `=` maybe?) – Tim Pietzcker Jan 14 '14 at 13:28
  • 1
    Not the example you posted here; if it doesn't work in your interpreter, something is seriously broken, *or* you didn't run the code you posted here. The `if True:` branch is always going to be executed, and if it is not, then certainly the `else:` branch is. Both branches bind a value to the name `a`. – Martijn Pieters Jan 14 '14 at 13:29

2 Answers2

1

When you create a variable within a function, like this

  def __init__(self):
    a = 3

it will be accessible only within that function. That's why both 1 and 2 are working. In the third case, you creating a local variable in one function and trying to access it in another function where the variable is not visible. That's why it fails.

In order to make the third case working, add the variable to the current object (self), like this

  def __init__(self):
    self.a = 3

And this has to be accessed with the current object only

  def f(self):
    print self.a

Edit:

Regarding the first statement, if you execute the if..else and the print statements like this, it works fine

>>> if True:
...     a = 3
... else:
...     a = 4
... 
>>> print a
3
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • 1
    Thanks, but please see edit. I know about `self.` to make a variable instance, but the question is completely different if you take into account that it doesnt work when tried in the interpreter – Thomas Jan 14 '14 at 13:27
  • 1
    @Thomas Please check my edit in my solution, which shows that first case also produces valid output – thefourtheye Jan 14 '14 at 13:29
1

In the third example, a is a local variable in __init__ and is discarded when that method ends. Within classes, you need to use self.a to keep it around:

class A:
  def __init__(self):
    self.a = 3
  def f(self):
    print self.a

Your other examples actually both work, because in both a is defined locally and printed within the same scope. To copy-paste example 1 from my interpreter (2.7.3):

>>> if True:
    a = 3
else:
    a = 4


>>> print a
3
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • 1
    Please see edit. I know about `self.` to make a variable instance, but the question is completely different if you take into account that it doesnt work when tried in the interpreter – Thomas Jan 14 '14 at 13:25
  • 1
    I have pasted the exact result I get from the interpreter for example 1, no `NameError` – jonrsharpe Jan 14 '14 at 13:29