Why no lexical scoping for a method within a class?

Discussion in 'Python' started by walterbyrd, Dec 17, 2008.

  1. walterbyrd

    walterbyrd Guest

    For a language as well structured as Python, this seems somewhat
    sloppy, and inconsistant. Or is there some good reason for this?

    Here is what I mean:

    def a():
    x = 99
    print x

    def b():
    print x

    a()
    b() # raises an exception because x is not defined.

    However in the methods are within a class, the scoping seems to work
    differently.

    class ab():
    def a(self):
    self.x = 99
    print self.x
    def b(self):
    print self.x

    i = ab()
    i.a()
    i.b() # this works, why no lexical scoping?
     
    walterbyrd, Dec 17, 2008
    #1
    1. Advertising

  2. walterbyrd wrote:

    > For a language as well structured as Python, this seems somewhat
    > sloppy, and inconsistant. Or is there some good reason for this?
    >
    > Here is what I mean:
    >
    > def a():
    > x = 99
    > print x
    >
    > def b():
    > print x
    >
    > a()
    > b() # raises an exception because x is not defined.
    >
    > However in the methods are within a class, the scoping seems to work
    > differently.
    >
    > class ab():
    > def a(self):
    > self.x = 99
    > print self.x
    > def b(self):
    > print self.x
    >
    > i = ab()
    > i.a()
    > i.b() # this works, why no lexical scoping?


    Because what you do is to create instance variables. Why do you expect them
    not working if you explicitly access them?

    The real analog of your example would be this:

    class ab():
    def a(self):
    x = 100
    print x

    def b(self):
    print x

    which provokes the same error.

    however, there *are* different scoping rules, classes don't create a lexical
    scope for their own variables:


    class foo(object):
    x = 100

    def a(self):
    print x


    Diez
     
    Diez B. Roggisch, Dec 17, 2008
    #2
    1. Advertising

  3. walterbyrd

    Guest

    On Dec 17, 10:19 am, walterbyrd <> wrote:
    > For a language as well structured as Python, this seems somewhat
    > sloppy, and inconsistant.  Or is there some good reason for this?
    >
    > Here is what I mean:
    >
    > def a():
    >     x = 99
    >     print x
    >
    > def b():
    >     print x
    >
    > a()
    > b() # raises an exception because x is not defined.
    >
    > However in the methods are within a class, the scoping seems to work
    > differently.
    >
    > class ab():
    >     def a(self):
    >         self.x = 99
    >         print self.x
    >     def b(self):
    >         print self.x
    >
    > i = ab()
    > i.a()
    > i.b() # this works, why no lexical scoping?


    If scoping worked as you want, how, pray tell, would you define object
    attributes?
     
    , Dec 17, 2008
    #3
  4. walterbyrd

    John Machin Guest

    On Dec 18, 2:19 am, walterbyrd <> wrote:
    > For a language as well structured as Python, this seems somewhat
    > sloppy, and inconsistant.  Or is there some good reason for this?
    >
    > Here is what I mean:
    >
    > def a():
    >     x = 99
    >     print x
    >
    > def b():
    >     print x
    >
    > a()
    > b() # raises an exception because x is not defined.
    >
    > However in the methods are within a class, the scoping seems to work
    > differently.
    >
    > class ab():
    >     def a(self):
    >         self.x = 99
    >         print self.x
    >     def b(self):
    >         print self.x
    >
    > i = ab()
    > i.a()
    > i.b() # this works, why no lexical scoping?


    Two questions for you:
    (1) If you were to change the sloppy inconsistent scoping mechanism in
    classes, what would you change it to?
    (2) What do you think of the following:
    class ab():
    def a(self):
    self.x = 99
    print self.x
    def b(me):
    print me.x
    ?
     
    John Machin, Dec 17, 2008
    #4
  5. walterbyrd

    Guest

    Quoth walterbyrd <>:
    > For a language as well structured as Python, this seems somewhat
    > sloppy, and inconsistant. Or is there some good reason for this?


    Yes. It's called Object Oriented Programming.

    > Here is what I mean:
    >
    > def a():
    > x = 99
    > print x
    >
    > def b():
    > print x
    >
    > a()
    > b() # raises an exception because x is not defined.
    >
    > However in the methods are within a class, the scoping seems to work
    > differently.
    >
    > class ab():
    > def a(self):
    > self.x = 99
    > print self.x
    > def b(self):
    > print self.x
    >
    > i = ab()
    > i.a()
    > i.b() # this works, why no lexical scoping?


    Because x is an attribute.

    If you don't understand what that means, read any introductory
    article on OOP.

    To give you a clue, if you had said:

    class ab():
    def a(self):
    x = 99
    print x
    def b(self):
    print x

    You'd have gotten the exception you expected (assuming x wasn't
    defined globally).

    --RDM
     
    , Dec 17, 2008
    #5
  6. walterbyrd

    r Guest

    I think there is a simpler answer to all this(not to take away from
    the other ones here though which are all great). When writing
    procedural code how would you like it if vars inside functions were
    automatically global. Your code with be blowing chunks in no time.
    Thats the reason for global declarations and instance.var :)
     
    r, Dec 17, 2008
    #6
  7. "walterbyrd" <> wrote in message
    news:...

    > However in the methods are within a class, the scoping seems to work
    > differently.


    Not really, self is a formal parameter to the function. It would be
    a strange language where a function's own arguments weren't in scope.

    > def b(self):
    > print self.x


    Try changing it to:

    def b(somethingotherthanself):
    print self.x
     
    Richard Brodie, Dec 17, 2008
    #7
  8. walterbyrd

    walterbyrd Guest

    On Dec 17, 10:00 am, r <> wrote:
    > When writing
    > procedural code how would you like it if vars inside functions were
    > automatically global. Your code with be blowing chunks in no time.


    That was my point - I consider python's ordinary use of lexical
    scoping to be a good thing, and I was wondering why this "good thing"
    was not used in classes, as well as outside of classes.
     
    walterbyrd, Dec 17, 2008
    #8
  9. walterbyrd

    walterbyrd Guest

    On Dec 17, 8:41 am, wrote:

    > If scoping worked as you want, how, pray tell, would you define object
    > attributes?- Hide quoted text -


    I suppose you could do this:

    class className():
    varname = "whatever"
    def fname(self, varname):
    . . . .

    Instead of having variable defined within methods to be global
    everywhere within the class.

    Anyway, it's not a matter of what I like, I am just trying to
    understand the reason behind the scoping rules.
     
    walterbyrd, Dec 17, 2008
    #9
  10. walterbyrd

    walterbyrd Guest

    On Dec 17, 9:04 am, wrote:

    > Yes.  It's called Object Oriented Programming.


    I think you mean it's *Python* Object Oriented Programming. I am not
    sure that every other OO language works like that.
     
    walterbyrd, Dec 17, 2008
    #10
  11. walterbyrd

    walterbyrd Guest

    On Dec 17, 10:17 am, "Richard Brodie" <> wrote:
    > Not really, self is a formal parameter to the function. It would be
    > a strange language where a function's own arguments weren't in scope.


    Thank you, that makes sense to me.
     
    walterbyrd, Dec 17, 2008
    #11
  12. walterbyrd

    r Guest

    On Dec 17, 12:20 pm, walterbyrd <> wrote:
    > On Dec 17, 10:00 am, r <> wrote:
    >
    > > When writing
    > > procedural code how would you like it if vars inside functions were
    > > automatically global. Your code with be blowing chunks in no time.

    >
    > That was my point - I consider python's ordinary use of lexical
    > scoping to be a good thing, and I was wondering why this "good thing"
    > was not used in classes, as well as outside of classes.


    The whole point for even writing a class is for shared attributes.
    Write procedural code if you don't like classes. When ever you see
    self.var think of it as Class.instance(var)... makes total sense to
    me? Obliviously you have not done much procedural coding or you would
    know why this HAS to be. sorry if i sound rude.
     
    r, Dec 17, 2008
    #12
  13. walterbyrd a écrit :
    > On Dec 17, 8:41 am, wrote:
    >
    >> If scoping worked as you want, how, pray tell, would you define object
    >> attributes?- Hide quoted text -

    >
    > I suppose you could do this:
    >
    > class className():
    > varname = "whatever"


    This defines a class attribute - that is, an attribute of the className
    class object, accessible either thru the className object or it's
    instances if not shadowed by an instance attribute by the same name/

    > def fname(self, varname):
    > . . . .
    >
    > Instead of having variable defined within methods to be global
    > everywhere within the class.


    There's nothing like a "variable defined within (a) method", because you
    never define methods in Python - only functions. So there's no
    difference in scoping rules for functions defined within a class
    statement block or outside a class statement block.


    > Anyway, it's not a matter of what I like, I am just trying to
    > understand the reason behind the scoping rules.


    Then you should start with understanding the scoping rules.
     
    Bruno Desthuilliers, Dec 17, 2008
    #13
  14. walterbyrd a écrit :
    > On Dec 17, 9:04 am, wrote:
    >
    >> Yes. It's called Object Oriented Programming.

    >
    > I think you mean it's *Python* Object Oriented Programming. I am not
    > sure that every other OO language works like that.



    Every OO languages having such a thing as a global variable makes a
    distinction between an instance attributes and a global variable. Your
    problem is that you are confusing variables and attributes. In Python,
    'anything.anyname' (note the dot) is the attribute 'anyname' of object
    'anything'.
     
    Bruno Desthuilliers, Dec 17, 2008
    #14
  15. walterbyrd

    Rhodri James Guest

    On Wed, 17 Dec 2008 15:19:32 -0000, walterbyrd <>
    wrote:

    > However in the methods are within a class, the scoping seems to work
    > differently.


    Not really. Hopefully this commentary will show you why.

    > class ab():
    > def a(self):
    > self.x = 99
    > print self.x
    > def b(self):
    > print self.x
    >
    > i = ab()

    This creates |i|, an instance of class |ab|. As yet it is pure and
    virgin, having nothing but the methods that it gets from |ab|. Soon this
    will change...

    > i.a()


    This creates an attribute |x| in |i|, and assigns the number 99 to it.

    > i.b() # this works, why no lexical scoping?


    This works because you ran |i.a()| first, so |i.x| exists and can be
    printed out. Lexical scoping is going on here, you're just mistaking
    what's being scoped; it's the |self| in |b|, which is in scope because
    it's a parameter. This particular |self| (the |i| you made earlier)
    happens to have an attribute |x|, so it all works. If however you'd
    written:

    j = ab()
    j.b()

    then Python would whinge mightily at you, claiming that it knoweth naught
    of this |x| attribute of which you speak, and can it go home now for this
    is a silly place. The |self| in |b| is still in lexical scope, though.

    --
    Rhodri James *-* Wildebeeste Herder to the Masses
     
    Rhodri James, Dec 18, 2008
    #15
  16. On Wed, 17 Dec 2008 22:19:43 +0100, Bruno Desthuilliers wrote:

    > Your
    > problem is that you are confusing variables and attributes. In Python,
    > 'anything.anyname' (note the dot) is the attribute 'anyname' of object
    > 'anything'.


    An easy mistake to make, given that scopes are just namespaces, and
    attribute access is just accessing names in namespaces too.


    --
    Steven
     
    Steven D'Aprano, Dec 18, 2008
    #16
  17. On Wed, 17 Dec 2008 10:20:21 -0800, walterbyrd wrote:

    > On Dec 17, 10:00 am, r <> wrote:
    >> When writing
    >> procedural code how would you like it if vars inside functions were
    >> automatically global. Your code with be blowing chunks in no time.

    >
    > That was my point - I consider python's ordinary use of lexical scoping
    > to be a good thing, and I was wondering why this "good thing" was not
    > used in classes, as well as outside of classes.


    But it is. You're mistaking lexical scoping for object attribute access.
    The rules for lexical scoping inside a class are (almost) the same as
    they are for inside a function:

    def parrot(breed):
    def message(colour):
    return "The %s %s has beautiful plumage." % (breed, colour)
    return message("Blue")

    class Parrot:
    def parrot(self, breed):
    def message(colour):
    return "The %s %s has beautiful plumage." % (breed, colour)
    return message("Blue")

    And in use:

    >>> parrot("Norwegian")

    'The Norwegian Blue has beautiful plumage.'
    >>> p = Parrot()
    >>> p.parrot("Swedish")

    'The Swedish Blue has beautiful plumage.'


    Notice that to have lexical scoping work, you actually have to nest the
    functions. Otherwise they are in different scopes.


    This might lead you believe you can do this:

    class Parrot2:
    colour = "Blue"
    def parrot(self, breed):
    return "The %s %s has beautiful plumage." % (breed, colour)


    >>> p = Parrot2()
    >>> p.parrot("Norwegian")

    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 4, in parrot
    NameError: global name 'colour' is not defined

    What's going on? Why doesn't the parrot method see the name "colour" in
    the class scope?

    The reason is that the class scope is deliberately left out of the nested
    scope chain. This was a design decision from when nested scopes were
    introduced:

    "An alternative would have been to allow name binding in class
    scope to behave exactly like name binding in function scope. This
    rule would allow class attributes to be referenced either via
    attribute reference or simple name. This option was ruled out
    because it would have been inconsistent with all other forms of
    class and instance attribute access, which always use attribute
    references. Code that used simple names would have been obscure."

    http://www.python.org/dev/peps/pep-0227/

    So inside the method, you need to refer to Parrot.colour (or thanks to
    the rules of attribute inheritance, self.colour).

    Classes could be closures, but that could radically change the way
    methods and classes work. Depending on design decisions, it might require
    huge changes to the Python compiler. How would it change the existing
    lexical scoping in factory functions?

    def factory(colour):
    class Parrot:
    def parrot(self, breed):
    return "The %s %s has beautiful plumage." % (breed, colour)
    return Parrot

    >>> redparrot = factory("Red")()
    >>> redparrot.parrot("Swedish")

    'The Swedish Red has beautiful plumage.'


    Consider a hypothetical Python with classes included in the lexical
    scoping:

    class Parrot3:
    colour = "Blue"
    def parrot(self):
    colour = "Red"


    What should method parrot do? I can think of at least three possibilities:

    * create a local name colour inside the method scope;
    * change the class attribute Parrot3.colour to "Red";
    * create an instance attribute self.colour.

    Whatever solution you come up with, there is potential inconsistency with
    other parts of the language.



    --
    Steven
     
    Steven D'Aprano, Dec 18, 2008
    #17
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,966
    Smokey Grindel
    Dec 2, 2006
  2. Matt Barnicle
    Replies:
    10
    Views:
    639
    Bruno Desthuilliers
    Dec 2, 2007
  3. Khookie

    C closures & lexical scoping

    Khookie, Dec 12, 2007, in forum: C Programming
    Replies:
    28
    Views:
    1,398
    cr88192
    Dec 15, 2007
  4. Aronaxis, the Sourceror

    (?{..}) and lexical scoping issues.

    Aronaxis, the Sourceror, Jun 20, 2004, in forum: Perl Misc
    Replies:
    3
    Views:
    214
    Anno Siegel
    Jun 21, 2004
  5. Louis.

    Lexical scoping question.

    Louis., Feb 10, 2005, in forum: Perl Misc
    Replies:
    8
    Views:
    197
    Michael Powe
    Feb 11, 2005
Loading...

Share This Page