Question about classes and possible closure.

James Stroud jstroud at mbi.ucla.edu
Thu Feb 22 00:28:37 EST 2007


Steven W. Orr wrote:
> This is all an intro learning experience for me, so please feel free to 
> explain why what I'm trying to do is not a good idea.
> 
> In the Cookbook, they have a recipe for how to create global constants.
> 
> -----------------
> class _const:
>     class ConstError(TypeError): pass
>     def __setattr__(self,name,value):
>         if self.__dict__.has_key(name):
>             raise self.ConstError, "Can't rebind const(%s)"%name
>         self.__dict__[name]=value
> 
> import sys
> sys.modules[__name__]=_const()
> ----------------
> 
> I'd like to be able to create constants within a class. (Yes I 
> understand that uppercase names is a far better and easier convention 
> but this is a learning experience for me.)
> 
> I can't get this to work, but my idea is that MyClass is defined thusly:
> 
> class ConstError(TypeError): pass
> class Myclass:
>     def mprint(self):
>         print "C1 = ", self._C1
> 
>     # Define a subclass to create constants. It refs upself to access
>     # the uplevel copy of self.
>     class _const:
>         class ConstError(TypeError): pass
>         def __setattr__(_upself,name,value):
>             if upself.__dict__.has_key(name):
>                 raise self.ConstError, "Can't rebind const(%s)"%name
>             else:
>                 print "Just set something"
>             upself.__dict__[name]=value
> 
>     # I want the const instance to be contained in this class so I
>     # instantiate here in the constructor.
>     def __init__(self):
>         upself = self
>         upself.consts = const()
>         upself.consts._C1 = 0
>         setattr(upself.consts, "_C1", 44)
>         self = upself
> 
> Then the call in another file is this:
> #! /usr/bin/python
> from c2 import Myclass
> foo = Myclass()
> foo.mprint()
> # end
> 
> Is it possible to nest a class in another class and is it possible to 
> make this work?
> 
> TIA
> 


I see no reason to nest classes, ever, as each creates a seperate name 
space. Better would be to de-nest _const and make it available to all of 
your classes, otherwise you have lost some of its reusability. A class 
is esentially the definition of a behavior and so nesting assumes that 
the nesting confers upon the outer class that having a nested class 
changes its behavior. This is what composition is for. If you want a 
reference to a class in your code, then make an assignment:


# Const.py
class ConstError(TypeError): pass

class Const:
   def __setattr__(self, name, value):
     if hasattr(self, name):
       raise ConstError, "Can't rebind const(%s)" % name
     else:
       print "Just set something"
     self.__dict__[name] = value


# Myclass.py
import Const

class Myclass:

      def mprint(self):
          print "C1 = ", self.consts._C1

      def __init__(self):
          self.consts = Const()
          self.consts._C1 = 0
          # This will raise an error!!!!
          self.consts._C1 = 44


This makes a lot more sense and follows the "flat is better than nested" 
  rule. Notice how, otherwise, ConstError would be triple nested. Now 
you can import Const and have constants in all your classes.

I also pythonized some of your code.

James



More information about the Python-list mailing list