Declaring a class level nested class?

C

cmckenzie

Hi.

I'm new to Python, but I've managed to make some nice progress up to
this point. After some code refactoring, I ran into a class design
problem and I was wondering what the experts thought. It goes
something like this:

class module:
nestedClass

def __init__():
self.nestedClass = nested()
print self.nestedClass.nestedVar

class nested():
nestedVar = 1
def __init__(self):
print "Initialized..."

I can't figure out what the correct way to construct the "nested"
class so it can belong to "module".

I want a class level construct of "nested" to belong to "module", but
I keep getting nestedClass isn't defined.

My example isn't great or 100% accurate, but I hope you get the idea.

Thanks.
 
C

Chris Rebert

Hi.

I'm new to Python, but I've managed to make some nice progress up to
this point. After some code refactoring, I ran into a class design
problem and I was wondering what the experts thought. It goes
something like this:

class module:
  nestedClass

  def __init__():
     self.nestedClass = nested()
     print self.nestedClass.nestedVar

  class nested():
     nestedVar = 1
     def __init__(self):
        print "Initialized..."

I can't figure out what the correct way to construct the "nested"
class so it can belong to "module".

I want a class level construct of "nested" to belong to "module", but
I keep getting nestedClass isn't defined.

Here's the scoping reason why it fails (remember that the nested class
is a class variable of the containing class):

<BEGIN PENDING FAQ SUBMISSION>

Why do I get errors when accessing class variables (a.k.a. static variables)?
-------------------------------------------------------------------------------------
If you try something like the following::

class Foo(object):
class_variable = 42

def method(self, x):
return x + class_variable


Foo().method(7)

You'll get an error about Python being unable to find the class variable::

Traceback (most recent call last):
...
NameError: global name 'class_variable' is not defined

This is because class-level scope is not consulted when looking up
plain names in methods. When looking up a name, the following scopes
are consulted, in order: Local variables, Variables in nested
functions, Global variables, and finally, Built-ins.

To refer to class variables, you must be more explicit. There are several
ways to go about it:

* Refer to the class by name::

def method1(self, x):
return x + Foo.class_variable

* Refer to the class of the object dynamically. If you class is
subclassed, this will allow the subclasses to override the value of
the class variable. ::

def method2(self, x):
return x + self.__class__.class_variable

* Exploit the fact that attribute lookups on an object fall back to
its class. Be warned that if you have both instance and class variables
with the same name, the instance variable will shadow
the class variable. ::

def method3(self, x):
return x + self.class_variable

* If your method is not truly an instance method
(i.e. does not utilize ``self``), make it a class method ::

@classmethod
def method4(cls, x):
return x + cls.class_variable

<END FAQ EXCERPT>

However, there's pretty much no reason to nest classes anyway in
Python (it's not Java!). Just make them both top-level in the file. If
one class is only used internally in the module, just use the normal
private naming convention of starting its name with an underscore.

Also note that class names should generally use StudlyCaps, and that
naming a class "module" is rather confusing.

Cheers,
Chris
 
I

inhahe

it seems to me like it should work just fine if you just take out the
second line where it just says nestedClass
 
J

Jean-Michel Pichavant

cmckenzie said:
Hi.

I'm new to Python, but I've managed to make some nice progress up to
this point. After some code refactoring, I ran into a class design
problem and I was wondering what the experts thought. It goes
something like this:

class module:
nestedClass

def __init__():
self.nestedClass = nested()
print self.nestedClass.nestedVar

class nested():
nestedVar = 1
def __init__(self):
print "Initialized..."

I can't figure out what the correct way to construct the "nested"
class so it can belong to "module".

I want a class level construct of "nested" to belong to "module", but
I keep getting nestedClass isn't defined.

My example isn't great or 100% accurate, but I hope you get the idea.

Thanks.
class module:

class nested:
nestedVar = 1
def __init__(self):
print "Initialized..."

def __init__(self):
self.nestedClass = module.nested()
print self.nestedClass.nestedVar

Python will not look into the current class scope when trying to resolve
"nested", that is why the explicit call including the scope is required.
The code above runs fine with python 2.5.

Jean-Michel
 
J

Jean-Michel Pichavant

Chris said:
Hi.

I'm new to Python, but I've managed to make some nice progress up to
this point. After some code refactoring, I ran into a class design
problem and I was wondering what the experts thought. It goes
something like this:

class module:
nestedClass

def __init__():
self.nestedClass = nested()
print self.nestedClass.nestedVar

class nested():
nestedVar = 1
def __init__(self):
print "Initialized..."

I can't figure out what the correct way to construct the "nested"
class so it can belong to "module".

I want a class level construct of "nested" to belong to "module", but
I keep getting nestedClass isn't defined.

Here's the scoping reason why it fails (remember that the nested class
is a class variable of the containing class):

[snip interesting reminder/faq]

However, there's pretty much no reason to nest classes anyway in
Python (it's not Java!).
A little bit off topic,ahere is a nested class pattern I'm using quite
often :

class Device
"""Holds the different device services."""

class OS: # UPPERCASE means it holds constants
"""Operating system of one device."""
VXWORKS = 'vxWorks'
ECOS = 'ecos'

def init(self, _os = None):
self.os = _os

device = Device(Device.OS.VXWORKS)

Whenever I get a Device instance in my code I can match its OS without
tedious imports:

# no "from whatever import Device" is required
if device.os is device.OS.VXWORKS:
print 'you are using vxWorks'


I'm using this pattern whenever I can now:
1/ it removes all magically 'inside code' defined strings or numbers,
only class attributes are used.
2/ if required, it allows to write complete and detailed documentation
for nested class constants
3/ you can match attributes with the nested class values without further
import, everything is accessible from the instance itself

JM
 
L

Lie Ryan

I can't figure out what the correct way to construct the "nested"
class so it can belong to "module".

which one you want?

1. The Outside's class contains a nested class
class Outside(object):
class Inside(object):
...

2. The Outside's class contains an instance of the nested class
class Outside(object):
class inside(object):
...
inside = inside()

3. The Outside's instance contains an instance of the nested class
class Outside(object):
class Inside(object):
...
def __init__(self):
self.inside = Outside.Inside()


4.
 

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

Forum statistics

Threads
473,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top