Question about classes and possible closure.

S

Steven W. Orr

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

--
Time flies like the wind. Fruit flies like a banana. Stranger things have .0.
happened but none stranger than this. Does your driver's license say Organ ..0
Donor?Black holes are where God divided by zero. Listen to me! We are all- 000
individuals! What if this weren't a hypothetical question?
steveo at syslang.net
 
D

Dustan

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

Looking ahead, this should be "self.consts._C1", not "self._Cl".
# Define a subclass to create constants. It refs upself to access
# the uplevel copy of self.

It's better to stick with the conventions. But regardless, you have to
be consistent, as we see in a moment.
class _const:
class ConstError(TypeError): pass

This is redundant. Even though this ConstError and the one defined
before the Myclass definition are in completely different scopes, so
there's no conflict, I doubt this is what you meant to do.
def __setattr__(_upself,name,value):

Notice your first argument here is "_upself", with an underscore.
if upself.__dict__.has_key(name):

Now you're using "upself", without an underscore, which is undefined.
raise self.ConstError, "Can't rebind const(%s)"%name

Now you're using "self", which is also undefined.
else:
print "Just set something"
upself.__dict__[name]=value

Once again, "upself" instead of "_upself".

Just follow the convention: always use "self".
# I want the const instance to be contained in this class so I
# instantiate here in the constructor.
def __init__(self):
upself = self

Why "upself = self"? You could just as easily use "self". Follow the
conventions.
upself.consts = const()

I'm guessing this is your error? That should be "upself.consts =
self._const()"
upself.consts._C1 = 0
setattr(upself.consts, "_C1", 44)

Obviously, this is going to raise an error, because you're redefining
_Cl.
self = upself

Again, why the weird juggling between self and upself? First of all,
self and upself are references to the same object right now, so "self
= upself" has no after-effect at all. Second of all, even if it did,
all it would be doing is reassigning the local variable "self" to a
different object; it has no effect on the object you're working with.
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?

Yes, it is possible to nest a class in another class. Yes, it is
possible to make this work. However, it is good practice to post your
error message along with your code, so we don't have to guess.

Here's an untested rewrite of your code:

class Myclass:
def mprint(self):
print "C1 = ", self.consts._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 _upself.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):
self.consts = const()
self.consts._C1 = 0
# This will raise an error!!!!
setattr(self.consts, "_C1", 44)
 
J

James Stroud

Steven said:
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
 
J

James Stroud

James said:
Steven said:
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

should be self.consts = Const.Const()

James
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top