[ python-Bugs-1382740 ] len() on class broken

SourceForge.net noreply at sourceforge.net
Fri Dec 16 23:52:25 CET 2005


Bugs item #1382740, was opened at 2005-12-16 13:18
Message generated for change (Settings changed) made by kquick
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1382740&group_id=5470

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: Python Interpreter Core
Group: Python 2.4
>Status: Open
Resolution: Invalid
Priority: 5
Submitted By: Kevin Quick (kquick)
Assigned to: Nobody/Anonymous (nobody)
Summary: len() on class broken

Initial Comment:
With the following python input:

class A:
    @classmethod
    def __len__(cls):
        return 12

print '1',A.__len__()
print '2',A().__len__()
print '3',len(A())
print '4',len(A)

The output always breaks for '4' with 'TypeError: len 
of unsized object'

Same result for @staticmethod or normal instance method 
declaration.


----------------------------------------------------------------------

>Comment By: Kevin Quick (kquick)
Date: 2005-12-16 15:52

Message:
Logged In: YES 
user_id=6133

That would indeed solve '4', but has a non-orthogonality of 
attribute propagation that I don't understand and which 
seems inconsistent.

In my original:
  '1' demonstrates that __len__ is indeed in the dictionary
      for the class.
  '2' shows the expected attribute propagation effects: if
      at attribute is not found in the instance dictionary,
      the class dictionary is checked.
  '3' shows that len is implemented (generally) by looking
      for a __len__ method on the object in question.
  '4' confuses me, because it means that '3' isn't quite
      correct...

With your metaclass solution (using "__metaclass__ = meta" 
:) it does indeed make '4' work, and '1', but '2' and '3' 
now do not work, showing that instance-->class propagation
does not follow instance-->class-->metaclass.  Or something
...

Approaching this a different way:

My understanding of @classmethod (or perhaps more properly
@staticmethod) is that it allows "constant" methods that are
independent of the particular object instance.  So if I had:

class C:
  @staticmethod
  def f(): return 1

then both C.f() and C().f() are valid and return 1.

Why the len() translation to __len__ works *differently*
is strange.  I'm still defining a method, just one that
I want Python to use for any len(A) or len(A()) refs,
translating those to A.__len__() or A().__len__() and using 
those just as for C and f, respectively.


----------------------------------------------------------------------

Comment By: Reinhold Birkenfeld (birkenfeld)
Date: 2005-12-16 14:43

Message:
Logged In: YES 
user_id=1188172

You want to use a metaclass:

class meta(type):
    def __len__(cls):
        return 12

class B:
    __metaclass__ = B

print len(B)

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1382740&group_id=5470


More information about the Python-bugs-list mailing list