is meant by whom, and according to what rationale?
Because it it consistent with passing an empty bases-tuple to type,
which is where a non-empty bases-tuple goes. (See more on metaclass logic below).
+1
It does. The statement "class X():" imply there's no superclass, so it
definitiveley should behave the same as "class X:".
I'm not sure what you mean by "no superclass," comparing
[QUOTE= said:
>>> class Y(object): pass ...
>>> y = Y()
>>> type(y).mro()
[/QUOTE]
[<class '__main__.Y'>, <type 'object'>]
The way I look at it, in new-style-capable Python,
class X: pass
is really effectively sugar for
class X: __metaclass__ = types.ClassType
and
class X(bases): pass
is sugar for
class X(bases): __metaclass__ = type
so
class X(): pass
ought to be sugar for
class X(): __metaclass__ = type
I.e., "old-style classes" really inherit methods from a metaclass that overrides
the methods of object, so that new-style descriptor logic can be tweaked to provide the
old behaviors for classes not having type as metaclass.
and expliciteness could sometimes be
sacrified to simplify the life of developer: ex "abcd"[0:3] ->
"abcd"[:3].
Here there's no ambiguity.
And for newbies, the somewhat magic behavior of the "object" superclass
is not so clear even that it is very explicit.
There's no magic involved here. And I really doubt that having
inconsistant behaviour for "class X():" wrt/ "class X:" will help here.
Again, IMO any bases-tuple including empty should be sugar for __metaclass__ = type, i.e.,
class X(): pass
should be consistent with the empty parens in
X = type("X",(),{}),
not with the backwards-compatibility cleverness (really) of effectively
switching default metaclass to
X = types.ClassType("X",(),{})
using an empty and valid base class tuple as a flag for the switcheroo. Note that the code
erroneously creates an empty tuple for class X
ass, as if it were class X()
ass.
(IMO the proper way to indicate the you don't have a tuple is to use None or some other sentinel,
not abuse a perfectly legal tuple value).
1 0 LOAD_CONST 0 ('X') <<--+-- ought to be LOAD_CONST 0 (None)
3 BUILD_TUPLE 0 <<--'
6 LOAD_CONST 1 (<code object X at 02EE7EA0, file "", line 1>)
9 MAKE_FUNCTION 0
12 CALL_FUNCTION 0
15 BUILD_CLASS
16 STORE_NAME 0 (X)
19 LOAD_CONST 2 (None)
22 RETURN_VALUE
vs code for class x(something)
ass
1 0 LOAD_CONST 0 ('X')
3 LOAD_NAME 0 (object)
6 BUILD_TUPLE 1
9 LOAD_CONST 1 (<code object X at 02EFB9A0, file "", line 1>)
12 MAKE_FUNCTION 0
15 CALL_FUNCTION 0
18 BUILD_CLASS
19 STORE_NAME 1 (X)
22 LOAD_CONST 2 (None)
25 RETURN_VALUE
IMO generating an empty tuple for class X()
ass is a natural variation of the immediately above.
What is un-natural is using an empty tuple as a logical flag for old-style classes (implementing
the latter by selecting types.ClassType as the metaclass instead of type)
for what would othewise work perfectly normally with the default metaclass of type.
Code generation would need to provide something other than an empty tuple
on the stack for class X
ass (IWT None would work?) as the logic flag for old-style classes,
and build_class in ceval.c would have to be changed to recognize
the new flag value (None?) for calling types.ClassType,
and pass tuples (including empty) through to type.
so for now put
__metaclass__ = type
once at the top of your module source, and all your
class X:
...
will be interpreted as
class X:
__metaclass__ = type
...
instead of implicitly as
class X:
__metaclass__ = types.ClassType
...
Please repeat this 101 times each morning:
"thou shall not use old-style classes for they are deprecated".
(snip)
It's mostly a good way to add inconsistency and confusion to a situation
that's already confusing enough for newbies.
I don't agree with your idea of inconsistency.
IMO it would be better to explain that a legal basetuple value (empty tuple) is currently
being abused as a logical flag to call types.ClassType(clsname, basestuple, clsdict)
instead of type(clsname, basestuple, clsdict), and explain that it will be corrected, so that
class X()
ass will now call the latter, consistent with class X(bases)
ass.
Bottom line: IMO class C()
ass should create a new-style class,
and the parens serve well as a reminder of which kind it is, whether empty or not,
until py3k.
I.e., make it easy for newbies: parens means new-style, no parens means old-style, until py3k.
Pontificating pushes my counter-pontificating button; that's the only explanation
I have for doing this. I was going to stop wasting time, but find myself
unable as yet fully to abandon scanning clp and python-dev ;-/
Regards,
Bengt Richter