[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Quirk difference between classes and functions

On Tue, Feb 26, 2019 at 6:58 AM DL Neil <PythonList at danceswithmice.info> wrote:
> On 26/02/19 5:25 AM, ast wrote:
> > I noticed a quirk difference between classes and functions
> >  >>> x=0
> >  >>> class Test:
> >          x = x+1
> >          print(x)
> >          x = x+1
> >          print(x)
> ...
> > Previous code doesn't generate any errors.
> > x at the right of = in first "x = x+1" line is
> > the global one (x=0), then x becomes local
> > within a function, this is not allowed
> >  >>> x = 0
> >  >>> def f():
> >          x = x+1
> >  >>> f()
> > UnboundLocalError: local variable 'x' referenced before assignment
> > Since x is written inside the function, it is considered as a local
> > variable and x in x+1 is undefined so this throw an exception
> > Any comment ?
> At first I misunderstood the question, and even now I'm slightly mystified:-
> Is the observation to do with the principles of "closure" (being applied
> to the function) compared with the differences between class and
> instance variables?

Classes and functions behave differently. Inside a function, a name is
local if it's ever assigned to; but in a class, this is not the case.
(Honestly, I'm not sure why this is, but it's hardly ever significant;
metaprogramming seldom runs into this kind of thing.)

> A question from me: (I'm not an O-O 'native' having taken to it long
> after first learning 'programming') I've used class attributes to hold
> 'constants', eg
>         MAXIMUM_WEIGHT = 100
> Thus only an assignment to which reference/assertions will be made 'later'.
> I have initialised a counter to zero and then incremented within the
> instantiated object's __init__(), ie keeping track of how many of 'these
> objects' have been instantiated.

Once you're inside a method, you would reference it with a dot -
either "self.MAXIMUM_WEIGHT" or "cls.MAXIMUM_WEIGHT". So it's now an
attribute, not a local name.

> So, I can imagine taking a value from outside the class' namespace,
> modifying it in some way (per the first "x = x+1") and then retaining
> the result as a class attribute (a calculation performed once - when the
> class code is compiled).

Yes, this is perfectly legitimate. Not common but legit.

> However, (after that first calculation/definition of the class
> attribute) why would one (normally) want to redefine the same class
> attribute (the second x = x+1), at the 'class level'?
> (perhaps just done for its amusement value?)

That would not be common either. If you're redefining a variable
multiple times within a class block, you probably don't also have it
at top level. (For instance, you can put a "for" loop inside a class
statement to create attributes/methods, but the loop variable is
unlikely to also be a global.)

But hey! It's fun! :)