0
class blah(object):
  def __init__(self):
    self.x=5

blahinstance=blah()

def testclass():
  blahinstance.x+=1
  print blahinstance.x

testclass()  #blah will be incremented

print blahinstance.x #the incremented value holds after function exit
"------------------------------------------------------------------------------------"

x=5

def test():
  x+=1
  print x

print x
test() #fails because ref before assignemnt

So we have read access and modify access to global variables inside a local scope, but obviously attempts at re-assignment will just create a local variable of the same name as the global variable. In the examples above, what is different about referencing the instance attribute blahinstance.x which is outside of the functions scope? To me these examples are quite similar yet one fails and one does not. We do not have a ref before assignment error with blahinstance.x despite the fact that this object is in the global scope, similar to the second example of x.

To clarify - i totally understand the second example, and global vs local scope. What I don't understand is why the first works because it seems similar to the second. Is it because the instance object and it's attribute are mutable, and we have read/modify access to globals in a local scope?

Solaxun
  • 2,732
  • 1
  • 22
  • 41
  • See http://stackoverflow.com/questions/14081308/why-is-not-the-keyword-global-not-required-in-this-case – David Robinson Aug 25 '14 at 19:34
  • You're basically having the same issue as described in this question: [Python globals, locals, and UnboundLocalError](http://stackoverflow.com/questions/404534/python-globals-locals-and-unboundlocalerror). I know there's a better dupe somewhere, I just can't find it. – Lukas Graf Aug 25 '14 at 19:39
  • This is unrelated. I already stated that I understand local scope has read and modify (for mutable) access to global variables. Maybe my question was unclear? Or is it because the instance object and it's attribute are mutable the same way a list or dict would be, whereas an integer is not? Maybe this is what I did not understand, that the instance is mutable? – Solaxun Aug 25 '14 at 19:39
  • `x` (an integer) is not mutable though. – Lukas Graf Aug 25 '14 at 19:42

1 Answers1

0

Bare names are different from attribute references.

There is no name blahinstance.x. There is a name blahinstance, and the object it refers to has an attribute called x. When you do something like blahinstance.x += 2, the only variable you're referencing is blahinstance, and you're not assigning a new value to blahinstance, so all is well. The use of x in blahinstance.x is totally "internal" to blahinstance, and x is not really a variable at all, it's just an attribute name.

The "local variable referenced before assignment" business only comes into play when you assign to a variable --- that is, a bare name --- not an attribute reference, an item reference, or anything else. In this regard blahinstance.x += 2 is no different than somelist[1] += 2; x in the first case is no more a local variable than the index 1 is in the second case.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384