Re: [Tutor] Local variable look up outside the function and method
On Sun, May 12, 2019 at 8:05 AM Arup Rakshit wrote: > > In the following the function, x is reachable outside the scope of foo > function. > > In [1]: x = 10 > > In [2]: def foo(): >...: return x >...: > > In [3]: print(foo()) > 10 To what the others have said I wish to point out that if x is reassigned _inside the function_ x's scope is now local inside the function while x also still has a module scope. Consider: 3.6.8: x = 10 3.6.8: def foo(): ... x = 5 ... print("In foo x =", x) ... 3.6.8: foo() In foo x = 5 3.6.8: print("In module scope, x =", x) In module scope, x = 10 boB ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Local variable look up outside the function and method
Hello Arup, > In the following the function, x is reachable outside the scope of foo > function. > In [1]: x = 10 > In [2]: def foo(): >...: return x > In [3]: print(foo()) > 10 > But why it is not the case when the look up happens inside a > instance method of a class? > > In [1]: class Foo: >...: x = 10 >...: def bar(self): >...: return x > In [2]: Foo().bar() > --- > NameError Traceback (most recent call last) > in > > 1 Foo().bar() > > in bar(self) > 2 x = 10 > 3 def bar(self): > > 4 return x > > NameError: name 'x' is not defined > > I figured I have to access it like: > > In [1]: class Foo: >...: x = 10 >...: def bar(self): >...: return self.__class__.x >...: >...: print(Foo().bar()) > 10 > > Just want to know how these search happens in 2 contexts. Probably the following is the best section of the documentation to read: https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables Here's also a little sample that may help. By the way, I wouldn't normally be doing things like "unset self.x" and creating those peculiar methods, but I thought it might be instructive in this case. This is using the same sort of technique you were with your class called Foo. (I don't know all of the reasons why to inherit from object, but I usually do...) class Foo(object): x = 10 # -- class variable def __init__(self): self.y = 20 # -- instance variable named 'y' def setinstancex(self, x): self.x = x def removeinstancex(self): del self.x def report(self): return (self.x, self.y) if __name__ == '__main__': f = Foo() print('# -- f.x retrieves class value, f.y instance value') print('f.x = %s, f.y = %s, Foo.x = %s' % (f.x, f.y, Foo.x)) print() f.setinstancex(3.14159) print('# -- f.x retrieves instance value, f.y instance value') print('f.x = %s, f.y = %s, Foo.x = %s' % (f.x, f.y, Foo.x)) print() print('# -- warning, we are about to change the value for Foo.x') print() Foo.x = 6.022141e-23 print('# -- f.x retrieves class value, f.y instance value') print('f.x = %s, f.y = %s, Foo.x = %s' % (f.x, f.y, Foo.x)) print() f.removeinstancex() print('# -- f.x retrieves class value, f.y instance value') print('f.x = %s, f.y = %s, Foo.x = %s' % (f.x, f.y, Foo.x)) print() Good luck, -Martin -- Martin A. Brown http://linux-ip.net/ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Local variable look up outside the function and method
On 12/05/2019 14:04, Arup Rakshit wrote: The first case x is a global variable - which in Python really means module level. In the second case you have placed it inside Foo so you need to specify that that is where it is located. Classes encapsulate their own methods and attributes, that is one of their purposes. and just as you can't access a method without preceding it with self similarly you can't access an attribute without providing the object or class reference. > I figured I have to access it like: > > In [1]: class Foo: >...: x = 10 >...: def bar(self): >...: return self.__class__.x Remember that any time you find yourself using dunder techniques ask if there is an easier way. There usually is... You can just use return self.x or, possibly better: return Foo.x You know x is declared in the context of Foo so refer to it directly. The self approach runs the risk of an instance attribute of the same name being created and overriding the class attribute. (But sometimes that's what you want.) If you had an inheritance hierarchy where x was defined in multiple places the .__class__ approach would work better (probably even be needed). But in most cases these kinds of variables are defined once in the class and you are safe to access it by name - and it makes the code more readable and unambiguous. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor