Nested class structures

O

OKB (not okblacke)

For a variety of reasons, I'm interested in putting together some
code that will allow me to created structures out of nested classes,
something like:

class class1:
def methA(self):
print "Some code here"
class class2:
propA = "A"
def methB(self):
print "Some more code here"
class class3:
# etc.
class class4:
pass
#etc

The main problem is that Python does not seem to provide enough
information about the lexical context of definitions like this. In
particular, I would like the ability to have some of the nested classes
be "anonymous" -- that is, I don't want to have to worry about choosing
identifiers for them. I'd LIKE to do this:

class class1:
class anon: pass
class anon: pass
class anon: pass

. . . and somehow intercept or monitor the name-binding that's
going on there so I wind up with three separate classes which are bound
to uniquely named attributes of class1. But I can't do this because
each anon stomps on the previous name binding, and there doesn't seem to
be a way to intervene and bind a new attribute in class1, because class1
isn't really created until after all the nested class definitions
happen.

I've been playing around with various metaclass approaches, but I
can't seem to get it to really work. (In the nested class structures,
the metaclass instantiations happen from the bottom up, and that's the
main snag.) Are there any hooks or hacks that would allow me to affect
the way nested class definitions are bound to the attribute names of an
enclosing class definition? Or alternatively, a way to construct on the
fly a separate list or tree that reflects the nesting structure?

--
--OKB (not okblacke)
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is
no path, and leave a trail."
--author unknown
 
R

Russell Blau

OKB (not okblacke) said:
For a variety of reasons, I'm interested in putting together some
code that will allow me to created structures out of nested classes,
something like:

class class1:
def methA(self):
print "Some code here"
class class2:
propA = "A"
def methB(self):
print "Some more code here"
class class3:
# etc.
class class4:
pass
#etc

The main problem is that Python does not seem to provide enough
information about the lexical context of definitions like this. In
particular, I would like the ability to have some of the nested classes
be "anonymous" -- that is, I don't want to have to worry about choosing
identifiers for them. I'd LIKE to do this:

class class1:
class anon: pass
class anon: pass
class anon: pass

. . . and somehow intercept or monitor the name-binding that's
going on there so I wind up with three separate classes which are bound
to uniquely named attributes of class1. But I can't do this because
each anon stomps on the previous name binding, and there doesn't seem to
be a way to intervene and bind a new attribute in class1, because class1
isn't really created until after all the nested class definitions
happen.

I don't really understand what it is you are trying to do, but...

you can create an "anonymous" class object with:

type("anon", (object,), {})

This returns an object that is functionally identical to the object created
by:

class anon(object):
pass

Of course, you'll need to store the returned object somewhere to do anything
useful with it.
 
L

Larry Bates

It is a little hard to understand what you want but you
may just want to put class instances in a list.

class anon:
pass

class class1:
def __init__(self):
self.l=[anon(), anon(), anon()]

Now create an instance of class1:

x=class1()

x.l[0] will point to first instance of anon class
x.l[1] will point to second instance of anon class
x.l[2] will point to third instance of anon class

May not be what you are looking for.

Larry Bates
Syscon, Inc.
 
O

OKB (not okblacke)

Larry said:
It is a little hard to understand what you want but you
may just want to put class instances in a list.

class anon:
pass

class class1:
def __init__(self):
self.l=[anon(), anon(), anon()]

Yeah, sorry, I should have been a little more clear. Anyway, it's
important that these be actual class definitions, because I want the
ability to include per-class methods and stuff. So I don't really want
a bunch of identical anonymous classes. I want something like:

class class1:
class anon:
def meth1(self): print "meth1"
class anon:
def meth1(self): print "different meth1"
class anon:
def meth1(self): print "another meth1"

This is why I want to define the classes inline, nested in the
other class. I'm trying to leverage the syntactic structure of class
definitions to get nested structures of code. It's somewhat akin to

a = { 'one': 1,
'nested': { 'two': 2, 'three': 3,
'nestnest': { 'four': 4, 'five': 5 }
}
'othernest': { 'six': 6 }
}

. . . except that I want the ability to include arbitrary python
code where I have 1, 2, 3 there (as dictionary values). As far as
I can tell, Python doesn't provide a way to define code as part of
a larger expression like this, except in a class definition.

--
--OKB (not okblacke)
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is
no path, and leave a trail."
--author unknown
 
D

Diez B. Roggisch

This is why I want to define the classes inline, nested in the
other class. I'm trying to leverage the syntactic structure of class
definitions to get nested structures of code. It's somewhat akin to

a = { 'one': 1,
'nested': { 'two': 2, 'three': 3,
'nestnest': { 'four': 4, 'five': 5 }
}
'othernest': { 'six': 6 }
}

. . . except that I want the ability to include arbitrary python
code where I have 1, 2, 3 there (as dictionary values). As far as
I can tell, Python doesn't provide a way to define code as part of
a larger expression like this, except in a class definition.

The only thing that comes to my mind is to create the classes from strings
you exec - that will allow you to captur the class before redefining it:


code = """class anon:
def foo(_):
print "%s"
"""

res = []
for i in "abc":
exec(code % i)
res.append(anon)

for c in res:
c().foo()


Apart from that, I don't see any way to accomplish this - and for good
reasons: classes as well as functions are only declarations - that means
that they are stored in a sort of symbol table. And as there is no such
thing like an order of declartions, the only thing to access them is their
name. In languages that don't allow for rebinging an identifier, you'll get
an error when trying to. In python, its silently rebinded.

The question is: _why_ do you want to do this? How do you want to access the
anonymous classes, if you were able to create them?

Apart from that, I don't thing that a simple naming scheme like anon_1,
anon_2 and so on is too bad...
 
J

John Lenton

Yeah, sorry, I should have been a little more clear. Anyway, it's
important that these be actual class definitions, because I want the
ability to include per-class methods and stuff. So I don't really want
a bunch of identical anonymous classes. I want something like:

class class1:
class anon:
def meth1(self): print "meth1"
class anon:
def meth1(self): print "different meth1"
class anon:
def meth1(self): print "another meth1"

This is why I want to define the classes inline, nested in the
other class. I'm trying to leverage the syntactic structure of class
definitions to get nested structures of code. It's somewhat akin to

a = { 'one': 1,
'nested': { 'two': 2, 'three': 3,
'nestnest': { 'four': 4, 'five': 5 }
}
'othernest': { 'six': 6 }
}

. . . except that I want the ability to include arbitrary python
code where I have 1, 2, 3 there (as dictionary values). As far as
I can tell, Python doesn't provide a way to define code as part of
a larger expression like this, except in a class definition.

Two things. First, I don't understand (you don't explain) your
requirement for the classes to be 'anonymous'; the example in the dict
can be made easily, with

class a:
one = 1
class nested:
two = 2
three = 3
class nestnest:
.
.
.


but obviously there's something more to it.

Second, a class is an object like any other; you can include it in a
dictionary (that's all a nested class is doing, really, with some
sugar to get at it in convenient ways), push it into a list,
whatever. They're even hashable, so you can use them as dictionary
keys.


--
John Lenton ([email protected]) -- Random fortune:
Don't tell any big lies today. Small ones can be just as effective.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)

iD8DBQFBQvSYgPqu395ykGsRAt9nAJ4+s2ujkLmAHQOvjT3UdB3QOpH7ZwCgvxBL
McgHXs2EEWfE5nsJwAyKBGM=
=kUaw
-----END PGP SIGNATURE-----
 
A

Alex Martelli

Diez B. Roggisch said:
The only thing that comes to my mind is to create the classes from strings
you exec - that will allow you to captur the class before redefining it:

You can capture before redefining without any need to exec:
.... anons=[]
.... class anon:
.... def method1(self): return 'the first'
.... anons.append(anon)
.... class anon:
.... def method1(self): return 'the second'
.... anons.append(anon)
.... class anon:
.... def method1(self): return 'the third'
.... anons.append(anon)
.... del anon
.... ....
the first
the second
the third
Apart from that, I don't see any way to accomplish this - and for good
reasons: classes as well as functions are only declarations - that means

No way! Classes as well as functions are perfectly fine objects.
Python has no 'declarations'.
that they are stored in a sort of symbol table. And as there is no such
thing like an order of declartions, the only thing to access them is their

These is no such thing as "an order of declarations" because there are
no such things as declarations. There are statements, and of course
there is an order of them, including the two, def and class, most
popularly used to create functions and classes respectively.

Generally, Python collects names and their correspondence to objects in
a dictionary, and a dictionary indeed has no ordering, so there is no
trace left of the order in which the names were added to the dictionary
(except that a name->value correspondence added later tramples over any
that might have been added earlier for that same name). Which is why I'm
using a list, and calls to its append method, in the above example.

The question is: _why_ do you want to do this? How do you want to access the

That is indeed totally mysterious to me. I have a decent grasp of what
can be done, but sometimes the deeper question of why anybody might ever
possibly want to do it escapes me totally, and this is such a case.


Alex
 
D

Diez B. Roggisch

The only thing that comes to my mind is to create the classes from
strings you exec - that will allow you to captur the class before
redefining it:

You can capture before redefining without any need to exec:
... anons=[]
... class anon:
... def method1(self): return 'the first'
... anons.append(anon)
... class anon:
... def method1(self): return 'the second'
... anons.append(anon)
... class anon:
... def method1(self): return 'the third'
... anons.append(anon)
... del anon

Thats a nice one. I always forget about the possibility to execute actual
code while a class is encountered by the interpreter. As always, I'm
impressed on the variety of things doable in python - even if they don't
appeal to me as exactly useful (in this special case I mean.)
No way! Classes as well as functions are perfectly fine objects.
Python has no 'declarations'.

The reason I said that was because of the way the debugger steps through the
code: If it comes to a def, it doesn't execute the body - naturally. But it
collects of course the function as callable. That I viewed that as sort of
declaration - but you are of course right that there is no such thing as an
actual declaration in python.
 
O

OKB (not okblacke)

Alex said:
... anons=[]
... class anon:
... def method1(self): return 'the first'
... anons.append(anon)
... class anon:
... def method1(self): return 'the second'
... anons.append(anon)
... class anon:
... def method1(self): return 'the third'
... anons.append(anon)
... del anon
... ...
the first
the second
the third
The question is: _why_ do you want to do this? How do you want to
access the

That is indeed totally mysterious to me. I have a decent grasp of
what can be done, but sometimes the deeper question of why anybody
might ever possibly want to do it escapes me totally, and this is
such a case.

Well, I'm still experimenting with it, and partly I'm just playing
around, but one possible thing I thought might come out of these nested
classes is the ability to define a GUI with a syntax that mirrors the
GUI's nested structure. So each class in the tree there would represent
some GUI component, and as the classes are created, some metaclass
tinkering instantiates them, massaging information from the class def
into the format required by the GUI library.

As far as the anonymous business, I'm beginning to think it may not
be that much of a necessity, but: the idea is, suppose I'm defining a
whole bunch of GUI objects like sizers or something. It's tiresome to
have to make sure they all have unique names, so I was hoping I could
create some Python code that would generate the names for me.

Your code, of course, works great, but I am interested in subsuming
the list creation and appending into the class definitions themselves,
to avoid writing "anons.append(anon)" a bunch of times. However, there
doesn't seem to be any way for the metaclass of a nested class to get at
the enclosing class namespace. In fact, after looking at the docs some
more, I see that this is an explicit exception to the normal scoping
rules. (The silver lining, though, is that it means I DON'T have to
come up with totally unique names: they only have to be unique within a
single enclosing class def, which makes it less of a burden to name the
classes explicitly.)

Anyway, thanks for the help, everyone!

--
--OKB (not okblacke)
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is
no path, and leave a trail."
--author unknown
 
A

Alex Martelli

Diez B. Roggisch said:
Thats a nice one. I always forget about the possibility to execute actual
code while a class is encountered by the interpreter. As always, I'm

Right, that's all you CAN execute at that time, actually -- a class body
is nothing but a generic suite of statements which execute in their own
scope.
impressed on the variety of things doable in python - even if they don't
appeal to me as exactly useful (in this special case I mean.)

Right about the usefulness, unless further clarified by the OP. But,
sure!

The reason I said that was because of the way the debugger steps through the
code: If it comes to a def, it doesn't execute the body - naturally. But it

Ah, right, 'def' itself is executed as soon as it's met, but it
"stashes" the body away for later, of course -- and it binds the name.

I.e.,
def name(...): function_body
is something like:

body = compile(function_body)
name = new.function('name', body, ...

for an appropriate value of ...;-). Just like 'class', more precisely,
class name(bases): classbody
is like the sequence:

classdict = {}
exec class_body in classdict
name = appropriate_metaclass('name', bases, classdict)

where appropriate_metaclass is usually type (except for classic classes
or when you're using a custom metaclass).

collects of course the function as callable. That I viewed that as sort of
declaration - but you are of course right that there is no such thing as an
actual declaration in python.

Right, and that's important because sometimes it's nice to put class and
def in conditionals, loops, etc -- knowing they're normal executable
statements lets you do that with tranquility. E.g.:

if we_are_debugging:
def f():
body with much debugging printout
else:
def f():
lean and mean body

You don't need different and special #if/#else, normal runtime if/else
suffice, exactly because def is a normal executable statement...


Alex
 

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,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top