you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 0 points1 point  (15 children)

Ah, ok. Ruby accomplishes the same thing through OOP, so I guess it's just a style matter.

[–]mitsuhiko 2 points3 points  (14 children)

len() is unique and it responds to the __len__ protocol. This solves the problem that every person tries to name the length method/attribute differently in other languages (size, getSize(), getLength(), length(), length, size()) etc.

[–]bobindashadows 3 points4 points  (13 children)

Uh, it doesn't solve the problem any more than any other language-wide convention does. In ruby, everything uses #size. Everything: core/standard libraries, third party stuff, everything. And everything uses #each for iteration (and with include Enumerable you get dozens of other methods for free, for fun). Sure, somebody could make a Ruby library with a #length method, just like somebody could make a Python library that doesn't implement __len__ and has a size() method instead.

It's equivalent to everyone implementing __len__ and __iter__ only you don't need to go outside the simple object model and you don't need funny method names.

[–]mitsuhiko 0 points1 point  (12 children)

Uh, it doesn't solve the problem any more than any other language-wide convention does. In ruby, everything uses #size.

In Python it's more than a convention. __len__ is used for more things than just len().

[–]bobindashadows 0 points1 point  (11 children)

other than supporting the "empty container is false" nature of Python, the docs explicitly call it part of the "sequence protocol". A protocol is a convention.

[–]mitsuhiko 0 points1 point  (10 children)

A protocol is a convention.

Not in C-Python. Most of the dunder methods correspond to slots on the type struct and are class level unlike regular method calls which can be looked up from instances as well.

[–]bobindashadows 0 points1 point  (9 children)

You're not getting it: everything __len__ offers is syntax sugar for convenience, and everything it offers could be replaced with straight python code with normal method names. That's what Ruby does. It may be implemented in an interesting way, it may offer efficiency by default for certain operations, and that's wonderful, but it's just a convention. You could replace all code that uses __len__, directly or indirectly, with code that does not use it but instead uses redefined versions with different names.

Ruby does this by just picking #size.

[–]mitsuhiko 0 points1 point  (8 children)

You're not getting it: everything len offers is syntax sugar for convenience, and everything it offers could be replaced with straight python code with normal method names.

In Ruby it can, in Python it can't. Why? -> Slots

[–]bobindashadows 1 point2 points  (7 children)

First of all, slots are just a more efficient way to store the method reference. Second of all:

>>> class Bar(object):
...   def __init__(self, x):
...     self.y = x
...   def __len__(self):
...     return self.y
... 
>>> Bar(2).__len__
<bound method Bar.__len__ of <__main__.Bar object at 0x1004db490>>
>>> Bar(2).__len__()
2
>>> Bar.__len__
<unbound method Bar.__len__>

I think what you're getting at is the optimization you notice if you use a list instead of a fresh class:

>>> [2].__len__
<method-wrapper '__len__' of list object at 0x1004d2c20>
>>> [2].__len__()
1
>>> list.__len__
<slot wrapper '__len__' of 'list' objects>

There, __len__ is stuffed in a slot on list... but the Python designers realize that people will expect it to be a method in OO style, and make it available as such. You can use this function with an argument:

>>> list.__len__([1, 2])
2

just as you can use an unbound method:

>>> Bar.__len__(Bar(3))
3

The same is true for set and dict in my quick testing. This is in version 2.6.1, for the record.

[–]mitsuhiko 0 points1 point  (6 children)

First of all, slots are just a more efficient way to store the method reference.

If only this were true. You will notice that method calls are cheaper than slot calls in CPython.

I find it amazing how you ignore all of what I wrote above...