Class-level variables - a scoping issue

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Mon Oct 11 01:02:12 CEST 2010


On Sun, 10 Oct 2010 18:14:33 -0400, John Posner wrote:

> Class attributes are often used as "class constants", so how about
> naming them with UPPERCASE names, like other constants? When you choose
> to override one of these constants, like this:
> 
>     self.EGGS = 4

Er what?

If self.EGGS is meant as a constant, you shouldn't be re-assigning to it 
*ever*.


> ... the awkward looks of the statement serve as a hint that something
> special is happening.

I disagree that anything special is happening. The current behaviour is, 
to my mind, the correct behaviour.


> #------------
> class SpamMeal:
>      EGGS = 2
> 
>      def __init__(self, egg_count=None):
>          if egg_count:
>              self.EGGS = egg_count
> 
>      def Report(self):
>          print "This meal includes %d eggs." % self.EGGS
> 
> meal = SpamMeal()
> meal.Report()    # "This meal includes 2 eggs."
> 
> meal = SpamMeal(3)
> meal.Report()    # "This meal includes 3 eggs."
> 
> meal = SpamMeal()
> meal.EGGS = 4
> meal.Report()    # "This meal includes 4 eggs."
#------------


Apart from the ugliness of the attribute name, this does not differ in 
the slightest from the current behaviour. How could it? Merely changing 
the attribute name "eggs" to "NAME" can't change the behaviour. Your 
SpamMeal instances still default to 2 eggs, assigning to instance.EGGS 
still creates an instance attribute while leaving SpamMeal.EGGS 
untouched, and it is still necessary to assign to SpamMeal.EGGS in order 
to globally change all instances (that don't already have their own EGGS 
attribute).

Since nothing has changed, what's the point? What exactly is the 
surprising behaviour that you are trying to flag?



-- 
Steven



More information about the Python-list mailing list