Why nested scope rules do not apply to inner Class?

Maric Michaud maric at aristote.info
Wed Aug 13 21:19:00 EDT 2008


Calvin Spealman a écrit :
> On Wed, Aug 13, 2008 at 7:41 PM, Maric Michaud <maric at aristote.info> wrote:
>> I was not aware of any "nested classes are unsupported" before and didn't
>> consider nested classes as bad practice till now, even with the pickle
>> limitation (not every class are intended to be pickled), more you didn't give
>> any evidence or any pertinent quote of this and at least one of Guido in the
>> above threads seems contradict you :
>> http://mail.python.org/pipermail/python-dev/2002-November/029906.html
> 
> Of course, I don't have to agree with Guido,

neither do I, for sure.

> but I don't really think
> his comment there counts as some encouragement of the practice. It
> also isn't an example that actually demonstrates the things people
> misuse about nesting classes, although its definitely an example that
> I think could be done much better without them, at all.
> 

Yes this example is some sort of metalanguage using class statment in a 
derived way, It comes in mind sometimes by the fact there is no other 
way to extend the language to make DSL in python (perhaps easy extend 
will be popular one day, but I doubt). I did something like that before 
in an application and won't encourage anyone to do so.

> The use of nested classes to define some hierarchical structure is
> subject, at best. And, the examples I see aren't even hierarchical.
> The nesting doesn't seem to gain them anything. As a matter of fact,
> wouldn't that example be a lot more clear with one class and some
> "Attribute" properties describing the structure?
> 
> What rubs me the wrong way about nested classes is that they aren't
> even "real" classes. That is, they aren't being used to instantiate
> instances, but just as dummy scopes to hold some attributes. They are
> abusing classes as property bags.
> 

Here, I disagree, the helper classes example is good IMO, defining an 
Iterator as an inner class and referencing it by MyIterable.Iterator is 
good style.

That said, I understood from your first post that python community in 
general will discourage nested classes as bad practice and consider them 
not supported by the language, statment for which I can't find or 
remember no evidence.

>> BTW my concern was not really about nested classes but the asymetry between
>> function scope and classes scope, there are at least two examples that come
>> to my mind and for which I don't see good argument to keep the situation as
>> it is. First is the very odd behavior of genexp, second is the dynamic type
>> factory, I know it's not a big deal to in each case and can live with this,
>> but these pieces of code fail unexpectedly while even a experimented python
>> programmer would have thought they work at first glance, and the explanation
>> of why they fail to a newcomer is not easy (specially for the first)
>>
>> (1) this fail  only on the last line while it would have work well with
>> listcomp and works well in a function definition
>> class A(object) :
>>    l = range(5)
>>    m = list(a+b for a in l for b in range(5))
>>    n = list(a+b for a in range(5) for b in l)
> 
> I can admit that this behavior can be surprising, but it isn't
> something I really see cropping up as a problem. How often do you see
> that you need to have any kind of procedural behavior in a class body?
> In other words, in all but rare cases, the order of the class body
> lines shouldn't change the resulting class, but this example breaks
> that expectation.
> 

I wrote something like that a few months ago, and found it both simple 
concise and elegant :

class test_suite1(test_suite) :
	roles = (role1, ...)
	actors = (actor1, ...)
	use_cases = [ (actor, role) for actor in actors for role in roles ]

which I wrote at first tuple((actor, role) for ...) and came to the problem.

Of course use_cases can be made a true generator, but in this particular 
case building the tuple/list together with the class is good enough.

>> (2) This won't work as it would with nested functions, you need to build the
>> new calss directly with type('dynamic', (object,), {"type_": type_})
>>
>> def create_type(type_) :
>>    class dynamic(object) :
>>        type_ = type_
>>    return dynamic
> 
> This is simply completely invalid. That code at the beginning of any
> body will _always_ raise either an UnboundLocalError or a NameError,
> because you are assigning to the same name you are dereferencing. That
> line will always be either an error or a no-op, anywhere it appears.
> It has nothing to do with nesting of any sort.
> 

Yes, of course, sorry, it should be :

def create_type(t) :
     class dynamic(object) :
         type_ = t
     return dynamic

but this work to my surprise ! I just thought the "t" in the class body 
would be looked up in global namespace. The design is that "free vars 
doesn't bind to class namespaces" not that "free vars of class 
namespaces bind to global namespace", my mistake.

>> --
>> _____________
>>
>> Maric Michaud
>> --
>> http://mail.python.org/mailman/listinfo/python-list
> 
> 
> 




More information about the Python-list mailing list