473,289 Members | 1,729 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,289 software developers and data experts.

A Python 3000 Question

Will len(a_string) become a_string.len()? I was just reading

http://docs.python.org/dev/3.0/whatsnew/3.0.html

One of the criticisms of Python compared to other OO languages is that
it isn't OO enough or as OO as others or that it is inconsistent. And
little things such as this seem to support those arguments. Not that it
matters really... just seems that classes with methods used in a more
consistent manner would be more appropriate in an OO langauage. Is there
a reason that len cannot be a method?

a_string.lower() makes sense, as does a_string.split(),
a_string.strip()... why not a_string.len()?
Oct 29 '07 #1
40 1898
brad <by*******@gmail.comwrites:
Will len(a_string) become a_string.len()? I was just reading

http://docs.python.org/dev/3.0/whatsnew/3.0.html

One of the criticisms of Python compared to other OO languages is that
it isn't OO enough or as OO as others or that it is inconsistent. And
little things such as this seem to support those arguments. Not that
it matters really... just seems that classes with methods used in a
more consistent manner would be more appropriate in an OO
langauage. Is there a reason that len cannot be a method?

a_string.lower() makes sense, as does a_string.split(),
a_string.strip()... why not a_string.len()?
I wonder why people always complain about `len` function but never
about `iter` or `pprint.pprint`? :)

And to answer the question. In OO programming generic functions
are no less important than classes and objects.

Regards,
Rob
Oct 29 '07 #2
Rob Wolfe wrote:
I wonder why people always complain about `len` function but never
about `iter` or `pprint.pprint`? :)
Not complaining. len is simple and understandable and IMO fits nicely
with split(), strip(), etc... that's why I used it as an example, but
list(), etc. could be used as examples as well:

a_string.list() instead of list(a_string)
And to answer the question. In OO programming generic functions
are no less important than classes and objects.
Do they not take away from the OOness of the overall language and
introduce inconsistencies?
Oct 29 '07 #3

"brad" <by*******@gmail.comwrote in message
news:fg**********@solaris.cc.vt.edu...
| Will len(a_string) become a_string.len()?

No.

I was just reading
| http://docs.python.org/dev/3.0/whatsnew/3.0.html

which says nothing about such a change, except for one in the opposite
direction: o.next() changes to next(o) which in turn calls o.__next__(),
just as len(o) calls o.__len__()

| One of the criticisms of Python compared to other OO languages is that
| it isn't OO enough or as OO as others or that it is inconsistent.

Python is object-based and has a nice user-defined type (class) system, but
I do not believe Guido has ever called it object oriented. So the
comparision is besides the point even if true.

| Is there a reason that len cannot be a method?

It corresponds to and calls method .__len__ , when such exists. Yes,
Python could have been designed differently, with no builtin functions, but
is was not. Python is also a functional language with first-class generic
functions.

| why not a_string.len()?

You are free to bypass builtins and call methods directly if you like:
a_string.__len__().

But consider rewriting the following:

def table(func, seq):
return zip(seq, map(func,seq))

table(len, ('', (), []))

If you *really* want to be super-OO, like functionless OO languages, you
can also call methods instead of using operator symbols, which in effect
are names of builtin functions.

Instead of a+b, write a.__add__(b). And so on.

Terry Jan Reedy

Oct 29 '07 #4
brad wrote:
One of the criticisms of Python compared to other OO languages is
that it isn't OO enough or as OO as others or that it is
inconsistent.
If OO meant "everything must be a method" then yes, Python wasn't
OO.
And little things such as this seem to support those
arguments. Not that it matters really... just seems that classes
with methods used in a more consistent manner would be more
appropriate in an OO langauage. Is there a reason that len cannot
be a method?
Is there any particular reason why it should be a method?
a_string.lower() makes sense, as does a_string.split(),
a_string.strip()... why not a_string.len()?
Just a fuzzy comment: lower, split and strip work specifically for
strings and/or sequence types, and return a modified copy of them
(or modify them directly, as with other methods like sorted or
shuffle). len, OTOH, works for much more objects and returns some
kind of norm that makes objects comparable and whose type is the
same for all objects.

To make a long story short: Most methods do specific things with
objects; but len is a common function to get a simple property of
an object.

Regards,
Björn

--
BOFH excuse #164:

root rot

Oct 29 '07 #5
brad wrote:
a_string.list() instead of list(a_string)
A string can be stripped, "lowercased" or split, but why should it
be able to be "listed"? IMHO, list is a conversion function to make
a list from something.
>And to answer the question. In OO programming generic functions
are no less important than classes and objects.

Do they not take away from the OOness of the overall language and
introduce inconsistencies?
Not at all. Explain, why should they? Functions can be objects, too.
And are in Python.

The inconsistencies arise, IMHO, if an OO language introduces
non-object types for performance reasons, after that gets wrapper
classes to wrap those primitives, and even later gets the ability
to automatically cast a primitive into a wrapper class instance.
That's just ugly.

Regards,
Björn

--
BOFH excuse #56:

Electricians made popcorn in the power supply

Oct 29 '07 #6
On Oct 29, 4:25 pm, brad <byte8b...@gmail.comwrote:
One of the criticisms of Python compared to other OO languages is that
it isn't OO enough or as OO as others or that it is inconsistent.
Python is less thoroughly OO than some other languages, yes. The
underlying assumption, that being thoroughly OO is a good thing, is
very dubious.
Carl Banks

Oct 29 '07 #7
On Mon, 29 Oct 2007 17:26:06 -0400, brad wrote:
Rob Wolfe wrote:
>I wonder why people always complain about `len` function but never
about `iter` or `pprint.pprint`? :)

Not complaining. len is simple and understandable and IMO fits nicely
with split(), strip(), etc... that's why I used it as an example, but
list(), etc. could be used as examples as well:

a_string.list() instead of list(a_string)
`list()` takes any iterable and turns it into a list object. That's a
generic operation coded *once*. If you have `str.list()`, `tuple.list()`,
`list.list()`, `dict.list()`, `file.list()`, `MyIterableSomething.list()`,
etc. you have to code the same over and over again for all those objects.
How could that be a benefit!?
>And to answer the question. In OO programming generic functions
are no less important than classes and objects.

Do they not take away from the OOness of the overall language and
introduce inconsistencies?
No not at all. Why do you think so? There are things that are best
expressed as functions. Other allegedly more OO languages have them
too, but you need to stuff them as static methods into classes or even
uglier you see code like ``Spam().spammify(eggs)`` instead of a plain
function call.

And functions are first class objects in Python. That sounds quite OO to
me. You can think of a module with functions as a singleton.

Ciao,
Marc 'BlackJack' Rintsch
Oct 30 '07 #8
Bjoern Schliessmann wrote:
The inconsistencies arise, IMHO, if an OO language introduces
non-object types for performance reasons, after that gets wrapper
classes to wrap those primitives, and even later gets the ability
to automatically cast a primitive into a wrapper class instance.
That's just ugly.
If you mean Java, then just say Java.

;)
/W
Oct 30 '07 #9
brad wrote:
Not complaining. len is simple and understandable and IMO fits nicely
with split(), strip(), etc... that's why I used it as an example, but
list(), etc. could be used as examples as well:

a_string.list() instead of list(a_string)
This is a great example of why list() needs to be a singleton and *not*
a method of any particular class. Consider the following contrived
object (yes object):

def foo():
for x in xrange(6):
yield x
If we eliminated list() as a first class singleton and forced it to be a
method call, how would it work with this generator object? Right now I
can say:

mylist=list(foo())

Saying list() should be a method only of something iterable is not only
foolish, but wasteful. Why should I burden every iterable object with
redundant code? And how would you deal with generators in your scenario?

In short, making list() a method is wrong-thinking. Reminds me of java.
Ugg.
>
>And to answer the question. In OO programming generic functions
are no less important than classes and objects.

Do they not take away from the OOness of the overall language and
introduce inconsistencies?
If find Python to be more OO through and through than Java. Once you
understand that functions are objects, and duck-typing, things like
len() being a function rather than a method make perfect sense.
Oct 30 '07 #10
On Oct 29, 5:49 pm, "Terry Reedy" <tjre...@udel.eduwrote:
I was just reading
|http://docs.python.org/dev/3.0/whatsnew/3.0.html

which says nothing about such a change, except for one in the opposite
direction: o.next() changes to next(o) which in turn calls o.__next__(),
just as len(o) calls o.__len__()
Ugh. A great example of complexification (if there's such a word).
| why not a_string.len()?

You are free to bypass builtins and call methods directly if you like:
a_string.__len__().

But consider rewriting the following:

def table(func, seq):
return zip(seq, map(func,seq))

table(len, ('', (), []))
table(lambda x:x.__len__(), ('',[],()))

What was the point again ?
If you *really* want to be super-OO, like functionless OO languages, you
can also call methods instead of using operator symbols, which in effect
are names of builtin functions.

Instead of a+b, write a.__add__(b). And so on.
True, if ones wants to go all the way to, say, Java. Operator
overriding though is pretty handy in terms of syntax sugar to give up,
especially for expressions that are identical or strongly similar from
a familiar context (e.g. maths). This cannot be claimed about len()
though. My main problem with len() is not so much the function/method
inconsistency, but rather that it doesn't apply to all (or even most)
objects. I am much less against, say, getattr(), being a function
since it makes sense for all objects. But why len()? At best it's a
subjective judgment call of where to draw the line, at worst it's
plain inconsistent.

And while we're at it, what's the rationale of len() insisting that
the return value is >=0 ? That also looks odd in a dynamic language
with a "we're all adults here" philosophy and much less hand-holding
in areas that matter more (e.g. allowed by default comparisons between
instances of different types - at least that's one of the warts Python
3 gets right).

George

Oct 30 '07 #11
On Oct 29, 9:35 pm, Michael L Torrie <torr...@chem.byu.eduwrote:
brad wrote:
Not complaining. len is simple and understandable and IMO fits nicely
with split(), strip(), etc... that's why I used it as an example, but
list(), etc. could be used as examples as well:
a_string.list() instead of list(a_string)

This is a great example of why list() needs to be a singleton and *not*
a method of any particular class.
The whole discussion about list() is moot since it's not a function
anyway, it's a type. As long as a list knows hows to initialize itself
given any iterable, it would be useless to require it as a method to
the iterables as well (unless perhaps there are significant
performance improvements when one can create a list much faster than
iterating through it).
Saying list() should be a method only of something iterable is not only
foolish, but wasteful. Why should I burden every iterable object with
redundant code?
Does the same argument apply for len() ? Nope, you still have to
define __len__. Having a builtin len() that calls the method __len__
seems (using your words) "not only foolish but wasteful".
In short, making list() a method is wrong-thinking. Reminds me of java.
Ugg.
Agreed, but you're beating a dead horse with list().
If find Python to be more OO through and through than Java. Once you
understand that functions are objects, and duck-typing, things like
len() being a function rather than a method make perfect sense.
Does the fact that index() or split() are methods make perfect sense
as well? I guess after some time using Python it does, but for most
unbiased users the distinction seems arbitrary.

George

Oct 30 '07 #12
On Mon, 29 Oct 2007 19:50:14 -0700, George Sakkis wrote:
On Oct 29, 5:49 pm, "Terry Reedy" <tjre...@udel.eduwrote:
>| why not a_string.len()?

You are free to bypass builtins and call methods directly if you like:
a_string.__len__().

But consider rewriting the following:

def table(func, seq):
return zip(seq, map(func,seq))

table(len, ('', (), []))

table(lambda x:x.__len__(), ('',[],()))

What was the point again ?
Beautiful is better than ugly!? ;-)

Ciao,
Marc 'BlackJack' Rintsch
Oct 30 '07 #13
Bjoern Schliessmann:
Is there any particular reason why it should be a method?

[..]

To make a long story short: Most methods do specific things with
objects; but len is a common function to get a simple property of
an object.
You said it. IMHO it really could be a *property*, say `object.len`.
It doesn't do something on the object, but rather gives some information
about its "state".

--
Thomas Wittek
Web: http://gedankenkonstrukt.de/
Jabber: st*********@jabber.i-pobox.net
GPG: 0xF534E231
Oct 30 '07 #14
brad a écrit :
Will len(a_string) become a_string.len()? I was just reading

http://docs.python.org/dev/3.0/whatsnew/3.0.html

One of the criticisms of Python compared to other OO languages is that
it isn't OO enough
Really ? IIRC, Python doesn't have primitive types, functions are
objects, methods are objects, classes are objects, even modules are
objects... Isn't this 'OO enough' ?
or as OO as others
Which ones ? Java, that does have primitive types ?

(snip question about len() not being a method - no personal opinion on
the topic)
Oct 30 '07 #15
brad a écrit :
Rob Wolfe wrote:
>I wonder why people always complain about `len` function but never
about `iter` or `pprint.pprint`? :)

Not complaining. len is simple and understandable and IMO fits nicely
with split(), strip(), etc... that's why I used it as an example, but
list(), etc. could be used as examples as well:

a_string.list() instead of list(a_string)
Oh, fine. And a_string.tuple(), a_string.int(), a_string.this(),
a_string.that() etc ?

In case you don't know, list is a type, not a function !-)
>And to answer the question. In OO programming generic functions
are no less important than classes and objects.

Do they not take away from the OOness of the overall language
Why so ?
and
introduce inconsistencies?
The monotonic approach to callables in Python (I mean: functions are
callable objects, classes are callable objects, so instanciation and
function call have the exact same syntax - which let you decouple
interface from implementation) is another way to be consistent. because
you can switch from type to factory function (or from closure to
callable object, etc) back and forth without breaking client code.
Oct 30 '07 #16
On Oct 29, 7:59 pm, Wildemar Wildenburger
<lasses_w...@klapptsowieso.netwrote:
Bjoern Schliessmann wrote:
The inconsistencies arise, IMHO, if an OO language introduces
non-object types for performance reasons, after that gets wrapper
classes to wrap those primitives, and even later gets the ability
to automatically cast a primitive into a wrapper class instance.
That's just ugly.

If you mean Java, then just say Java.
There was no need to; it was heavily implied.

Oct 30 '07 #17
On 10/29/07, brad <by*******@gmail.comwrote:
Will len(a_string) become a_string.len()? I was just reading

http://docs.python.org/dev/3.0/whatsnew/3.0.html

One of the criticisms of Python compared to other OO languages is that
it isn't OO enough or as OO as others or that it is inconsistent. And
little things such as this seem to support those arguments. Not that it
matters really... just seems that classes with methods used in a more
consistent manner would be more appropriate in an OO langauage. Is there
a reason that len cannot be a method?

a_string.lower() makes sense, as does a_string.split(),
a_string.strip()... why not a_string.len()?
This is a FAQ:
http://effbot.org/pyfaq/why-does-pyt...g-len-list.htm
--
http://www.advogato.org/person/eopadoan/
Bookmarks: http://del.icio.us/edcrypt
Oct 30 '07 #18
Eduardo O. Padoan wrote:
This is a FAQ:
http://effbot.org/pyfaq/why-does-pyt...g-len-list.htm
Thanks to all for the feedback. I'm no language designer. I just see and
hear these criticisms and I wanted to think through it a bit by posting
here. I now better understand generic functions and why they are used in
some cases.
Oct 30 '07 #19
On Tue, 30 Oct 2007 00:11:58 +0000, Marc 'BlackJack' Rintsch wrote:
>>And to answer the question. In OO programming generic functions are no
less important than classes and objects.

Do they not take away from the OOness of the overall language and
introduce inconsistencies?

No not at all. Why do you think so?
I disagree. I think they *do* take away from the overall Object-Oriented
nature of the language, and that is A Very Good Thing Indeed.

OO is a tool, and like any tool, it has it's uses and misuses. Some
things are best written as objects, some as imperative procedures, some
as functions. As you say:
There are things that are best expressed as functions.
Agreed. It is a *good thing* that Python doesn't try to be 100%
functional, or 100% Object Oriented, or 100% procedural.

(Aside: I think it a shame that there is one major paradigm that Python
doesn't have *any* support for at all: logic programming, like Prolog. I
don't quite know what it is good for, but I'd like to find out!)

Other allegedly more OO languages have them
too, but you need to stuff them as static methods into classes or even
uglier you see code like ``Spam().spammify(eggs)`` instead of a plain
function call.

I'm reminded of a very famous proverb from the Kingdom of the Nouns:

For the lack of a nail,
throw new HorseshoeNailNotFoundException("no nails!");

For the lack of a horseshoe,
EquestrianDoctor.getLocalInstance().getHorseDispat cher().shoot();

For the lack of a horse,
RidersGuild.getRiderNotificationSubscriberList().g etBroadcaster().run(
new BroadcastMessage(StableFactory.getNullHorseInstanc e()));

For the rest of the proverb, which is well worth reading, you'll have to
see here:
http://steve-yegge.blogspot.com/2006...-of-nouns.html

--
Steven.
(no, not that Steve in the URL)
Oct 30 '07 #20
On 2007-10-30, Eduardo O. Padoan <ed************@gmail.comwrote:
This is a FAQ:
http://effbot.org/pyfaq/why-does-pyt...g-len-list.htm
Holy Airy Persiflage Batman!

Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>import timeit
timeit.Timer('len(seq)', 'seq = range(100)').timeit()
0.20332271187463391
>>timeit.Timer('seq.__len__()', 'seq = range(100)').timeit()
0.48545737364457864

--
Neil Cerutti
Oct 30 '07 #21
On Oct 30, 11:25 am, Neil Cerutti <horp...@yahoo.comwrote:
On 2007-10-30, Eduardo O. Padoan <eduardo.pad...@gmail.comwrote:
This is a FAQ:
http://effbot.org/pyfaq/why-does-pyt...-some-function...

Holy Airy Persiflage Batman!

Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.>>import timeit
>timeit.Timer('len(seq)', 'seq = range(100)').timeit()
0.20332271187463391
>timeit.Timer('seq.__len__()', 'seq = range(100)').timeit()

0.48545737364457864
Common mistake; try this instead:

timeit.Timer('seqlen()',
'seq = range(100); seqlen=seq.__len__').timeit()

George

Oct 30 '07 #22
On 2007-10-30, Jean-Paul Calderone <ex*****@divmod.comwrote:
On Tue, 30 Oct 2007 15:25:54 GMT, Neil Cerutti <ho*****@yahoo.comwrote:
>>On 2007-10-30, Eduardo O. Padoan <ed************@gmail.comwrote:
>>This is a FAQ:
http://effbot.org/pyfaq/why-does-pyt...g-len-list.htm

Holy Airy Persiflage Batman!

Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>>>import timeit
timeit.Timer('len(seq)', 'seq = range(100)').timeit()
0.20332271187463391
>>>>timeit.Timer('seq.__len__()', 'seq = range(100)').timeit()
0.48545737364457864

Not sure what you're trying to demonstrate.
That len as a builtin can be faster than len as an attribute, and
doesn't need any further explanation than that.
Here's another pointless transcript, though:

exarkun@charm:~$ python -m timeit -s '
seq = range(100)
' 'len(seq)'
1000000 loops, best of 3: 0.211 usec per loop
exarkun@charm:~$ python -m timeit -s '
seq = range(100)
' 'seq.__len__()'
1000000 loops, best of 3: 0.317 usec per loop
exarkun@charm:~$ python -m timeit -s '
class X(object):
def __len__(self): return 100
seq = X()
' 'seq.__len__()'
1000000 loops, best of 3: 0.427 usec per loop
exarkun@charm:~$ python -m timeit -s '
class X(object):
def __len__(self): return 100
seq = X()
' 'len(seq)'
1000000 loops, best of 3: 0.701 usec per loop
exarkun@charm:~$

I guess we've learned that sometimes something is faster than
something else, and other times the contrary.
It demonstratess that len is faster than __len__ for lists (and
probably for all builtin types) but not for user defined type X
(and probably not for any user defined type).

Or it may demonstrate that I'm all wet. If so, I've brought my
shampoo.

But if I'm wrong about the performance benefits then I guess I'm
still in the dark about why len is a builtin. The only compelling
thing in the linked explation was the signatures of the guys who
wrote the artible. (Guido does admit he would, "hate to lose it
as a builtin," but doesn't explain why that should be a bad
thing).

--
Neil Cerutti
It isn't pollution that is hurting the environment; it's the impurities in our
air and water that are doing it. --Dan Quayle
Oct 31 '07 #23
On 2007-10-30, George Sakkis <ge***********@gmail.comwrote:
On Oct 30, 11:25 am, Neil Cerutti <horp...@yahoo.comwrote:
>On 2007-10-30, Eduardo O. Padoan <eduardo.pad...@gmail.comwrote:
This is a FAQ:
http://effbot.org/pyfaq/why-does-pyt...-some-function...

Holy Airy Persiflage Batman!

Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.>>import timeit
>>timeit.Timer('len(seq)', 'seq = range(100)').timeit()
0.20332271187463391
>>timeit.Timer('seq.__len__()', 'seq = range(100)').timeit()

0.48545737364457864

Common mistake; try this instead:

timeit.Timer('seqlen()',
'seq = range(100); seqlen=seq.__len__').timeit()
Why would I want to do that?

--
Neil Cerutti
These people haven't seen the last of my face. If I go down, I'm going down
standing up. --Chuck Person
Oct 31 '07 #24
On Oct 31, 8:44 am, Neil Cerutti <horp...@yahoo.comwrote:
On 2007-10-30, George Sakkis <george.sak...@gmail.comwrote:
On Oct 30, 11:25 am, Neil Cerutti <horp...@yahoo.comwrote:
On 2007-10-30, Eduardo O. Padoan <eduardo.pad...@gmail.comwrote:
This is a FAQ:
http://effbot.org/pyfaq/why-does-pyt...-some-function...
Holy Airy Persiflage Batman!
Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.>>import timeit
timeit.Timer('len(seq)', 'seq = range(100)').timeit()
0.20332271187463391
timeit.Timer('seq.__len__()', 'seq = range(100)').timeit()
0.48545737364457864
Common mistake; try this instead:
timeit.Timer('seqlen()',
'seq = range(100); seqlen=seq.__len__').timeit()

Why would I want to do that?

To realize that __len__ is actually faster than len in this case; your
second timing is dominated by the time to do attribute lookup.
George

Oct 31 '07 #25
On 2007-10-31, George Sakkis <ge***********@gmail.comwrote:
On Oct 31, 8:44 am, Neil Cerutti <horp...@yahoo.comwrote:
>On 2007-10-30, George Sakkis <george.sak...@gmail.comwrote:
On Oct 30, 11:25 am, Neil Cerutti <horp...@yahoo.comwrote:
On 2007-10-30, Eduardo O. Padoan <eduardo.pad...@gmail.comwrote:
This is a FAQ:
http://effbot.org/pyfaq/why-does-pyt...-some-function...
>Holy Airy Persiflage Batman!
>Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.>>import timeit
timeit.Timer('len(seq)', 'seq = range(100)').timeit()
0.20332271187463391
timeit.Timer('seq.__len__()', 'seq = range(100)').timeit()
>0.48545737364457864
Common mistake; try this instead:
timeit.Timer('seqlen()',
'seq = range(100); seqlen=seq.__len__').timeit()

Why would I want to do that?

To realize that __len__ is actually faster than len in this
case; your second timing is dominated by the time to do
attribute lookup.
I knew that going in. Making len a builtin saves us from writing
our own seqlen functions. ;)

--
Neil Cerutti
He's a guy who gets up at six o'clock in the morning regardless of what time
it is. --Lou Duva
Oct 31 '07 #26
On 2007-10-31, Duncan Booth <du**********@invalid.invalidwrote:
Obviously it isn't an absolute thing: lists and dictionaries do
have other methods in the user namespace, so the decision to
keep len out of that namespace is partly a judgement call, and
partly historical (I think tuples didn't used to have any
methods at all).
Thanks for the interesting note. I didn't know that tuples
originally had no methods. That made len mandatory, I suppose.

--
Neil Cerutti
The Pastor would appreciate it if the ladies of the congregation would lend
him their electric girdles for the pancake breakfast next Sunday morning.
--Church Bulletin Blooper
Oct 31 '07 #27
Neil Cerutti <ho*****@yahoo.comwrote:
On 2007-10-31, Duncan Booth <du**********@invalid.invalidwrote:
>Obviously it isn't an absolute thing: lists and dictionaries do
have other methods in the user namespace, so the decision to
keep len out of that namespace is partly a judgement call, and
partly historical (I think tuples didn't used to have any
methods at all).

Thanks for the interesting note. I didn't know that tuples
originally had no methods. That made len mandatory, I suppose.
Only if you think tuples are a sequence rather than a record. :)

Come to think of it, strings didn't have methods either, so len needed to
be a function to get the length of a string.

I'm not sure when tuples sprouted methods. Strings grew methods in 1.6, but
I think numbers and tuples may not have got any methods until the
introduction of new-style classes (Python 2.2)
Oct 31 '07 #28
On Oct 31, 8:44 am, Neil Cerutti <horp...@yahoo.comwrote:
On 2007-10-30, George Sakkis <george.sak...@gmail.comwrote:
On Oct 30, 11:25 am, Neil Cerutti <horp...@yahoo.comwrote:
On 2007-10-30, Eduardo O. Padoan <eduardo.pad...@gmail.comwrote:
This is a FAQ:
http://effbot.org/pyfaq/why-does-pyt...-some-function...
Holy Airy Persiflage Batman!
Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.>>import timeit
timeit.Timer('len(seq)', 'seq = range(100)').timeit()
0.20332271187463391
timeit.Timer('seq.__len__()', 'seq = range(100)').timeit()
0.48545737364457864
Common mistake; try this instead:
timeit.Timer('seqlen()',
'seq = range(100); seqlen=seq.__len__').timeit()

Why would I want to do that?
If your point is to measure the time of just the operation as
accurately as possible, you don't want the extra dict lookup in
seq.__len__ affecting things. Though it seems to me that if your
intention is to determine if builtin or method style is faster, it's
not such a great idea to replace the method call with a builtin call.

As for what benefit there is for len to be a builtin:

Python considers len to be an operator for all intents and purposes.
Python chose to spell this operator like a regular function, but it
could easily have given a special syntax to the length operation (for
instance, $#x).

Do you think that, if the length operation had its own syntax, people
would be saying "No, length shouldn't be an operator, it should be a
method"? I don't think so; length is a fundamental and ubiquitous
operation and it wouldn't be unreasonable to give it its own syntax.

That suggests to me that, when people complain that len should be a
method, their complaint is a superficial complaint about spelling.
They are not considering whether len is important enough to be an
operator or not.
Carl Banks

Oct 31 '07 #29
On Wed, 31 Oct 2007 14:45:59 +0000, Duncan Booth wrote:
>Thanks for the interesting note. I didn't know that tuples originally
had no methods. That made len mandatory, I suppose.
Only if you think tuples are a sequence rather than a record.
Even records have a length. The length of a record is the number of
fields it has.

--
Steven.
Oct 31 '07 #30
On Wed, 31 Oct 2007 13:14:41 +0000, George Sakkis wrote:
On Oct 31, 8:44 am, Neil Cerutti <horp...@yahoo.comwrote:
>On 2007-10-30, George Sakkis <george.sak...@gmail.comwrote:
On Oct 30, 11:25 am, Neil Cerutti <horp...@yahoo.comwrote:
On 2007-10-30, Eduardo O. Padoan <eduardo.pad...@gmail.comwrote:
This is a FAQ:
http://effbot.org/pyfaq/why-does-pyt...hods-for-some-
function...
>>
>Holy Airy Persiflage Batman!
>Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more
information.>>import timeit
timeit.Timer('len(seq)', 'seq = range(100)').timeit()
0.20332271187463391
timeit.Timer('seq.__len__()', 'seq = range(100)').timeit()
>0.48545737364457864
Common mistake; try this instead:
timeit.Timer('seqlen()',
'seq = range(100); seqlen=seq.__len__').timeit()

Why would I want to do that?


To realize that __len__ is actually faster than len in this case; your
second timing is dominated by the time to do attribute lookup.

What Neil has done is the correct thing to measure in this case.

What you have measured is a local optimization that is only useful when
you have a tight loop with lots of calls to the same len():
Len = sequence.__len__
while Len() < 100000:
foo(sequence)
But what Neil is measuring is relevant for the more general case of
calling len() on arbitrary objects at arbitrary times:

x = len(sequence)
y = 42 + len("xyz")
if len(records) == 12:
print "twelve!"
To get the benefit of the micro-optimization you suggested, you would
need to write this:

Len = sequence.__len__
x = Len()
Len = "xyz".__len__
y = 42 + Len()
Len = records.__len__
if Len() == 12:
print "twelve!"
Not only is that an especially ugly, confusing piece of code, it is also
counter-productive as you still have to do the method lookup every single
time.

Taking the method lookup is an apple-and-oranges comparison. It is useful
to know for the times when you don't want an apple, you want an orange
(i.e. the tight loop example above).

This is an apples-and-apples comparison:
>>import timeit
timeit.Timer("Len = seq.__len__; Len()", "seq = range(12)").repeat()
[1.3109469413757324, 0.7687380313873291, 0.55280089378356934]
>>timeit.Timer("len(seq)", "seq = range(12)").repeat()
[0.60111594200134277, 0.5977931022644043, 0.59935498237609863]
The time to do the lookup and call the method is about 0.6 microseconds
whether you do it manually or let len() do it.

The logic behind the micro-optimization trick is to recognize when you
can avoid the cost of repeated method lookups by doing it once only. That
is not relevant to the question of whether len() should be a function or
a method.

--
Steven.
Oct 31 '07 #31
On Wed, 31 Oct 2007 07:59:58 -0700, Carl Banks wrote:
Python considers len to be an operator for all intents and purposes.
Python chose to spell this operator like a regular function, but it
could easily have given a special syntax to the length operation (for
instance, $#x).
I hope you're not serious that $# would make a good operator. Apart from
conflicting with the comment marker, it is u-g-l-y.

That's the problem with operators... all the good ones are taken.

Do you think that, if the length operation had its own syntax, people
would be saying "No, length shouldn't be an operator, it should be a
method"? I don't think so; length is a fundamental and ubiquitous
operation and it wouldn't be unreasonable to give it its own syntax.
I think they would.

You seem to have missed the context of the thread. The Original Poster
was complaining that len() should be a method, because that is more
purely Object Oriented.

If len() were an operator, that too would be a compromise to the ideal of
"every function is an object method". I'm sure there are OO fan[atic]s
who dislike operators too.

--
Steven.
Oct 31 '07 #32
On Oct 31, 6:13 pm, Steven D'Aprano
What you have measured is a local optimization that is only useful when
you have a tight loop with lots of calls to the same len():

Len = sequence.__len__
while Len() < 100000:
foo(sequence)
Exactly what timeit() does, a tight loop.
But what Neil is measuring is relevant for the more general case of
calling len() on arbitrary objects at arbitrary times:

x = len(sequence)
y = 42 + len("xyz")
if len(records) == 12:
print "twelve!"

To get the benefit of the micro-optimization you suggested, you would
need to write this:

Len = sequence.__len__
x = Len()
Len = "xyz".__len__
y = 42 + Len()
Len = records.__len__
if Len() == 12:
print "twelve!"

Not only is that an especially ugly, confusing piece of code, it is also
counter-productive as you still have to do the method lookup every single
time.
The whole point of the optimization is avoiding 99999 attribute
lookups of the timeit loop. For a single call both times are
practically zero so the snippet above is just silly.
Taking the method lookup is an apple-and-oranges comparison. It is useful
to know for the times when you don't want an apple, you want an orange
(i.e. the tight loop example above).

This is an apples-and-apples comparison:
>import timeit
timeit.Timer("Len = seq.__len__; Len()", "seq = range(12)").repeat()

[1.3109469413757324, 0.7687380313873291, 0.55280089378356934]>>timeit.Timer("len(seq)", "seq = range(12)").repeat()

[0.60111594200134277, 0.5977931022644043, 0.59935498237609863]

The time to do the lookup and call the method is about 0.6 microseconds
whether you do it manually or let len() do it.
That assumes you know the internals of len(). Perhaps it does
something smarter for lists, or perhaps attribute lookup is faster at
the C level. I don't know, and that's exactly the point, I don't need
to know the internals to do the comparison of two callables.
The logic behind the micro-optimization trick is to recognize when you
can avoid the cost of repeated method lookups by doing it once only. That
is not relevant to the question of whether len() should be a function or
a method.
No disagreement here; I didn't bring up performance and it's not at
all a reason I consider len() as a function to be a design mistake.
What I dispute is Neil's assertion that "len as a builtin can be
faster than len as an attribute" and bringing as evidence the timings
that include attribute lookups. That statement is just wrong;
comparing X to an attribute assumes you have the attribute in the
first place, you don't need to look it up.

George

Oct 31 '07 #33
On Oct 31, 2007 6:02 PM, George Sakkis <ge***********@gmail.comwrote:
On Oct 31, 6:13 pm, Steven D'Aprano
What you have measured is a local optimization that is only useful when
you have a tight loop with lots of calls to the same len():

Len = sequence.__len__
while Len() < 100000:
foo(sequence)

Exactly what timeit() does, a tight loop.
But what Neil is measuring is relevant for the more general case of
calling len() on arbitrary objects at arbitrary times:

x = len(sequence)
y = 42 + len("xyz")
if len(records) == 12:
print "twelve!"

To get the benefit of the micro-optimization you suggested, you would
need to write this:

Len = sequence.__len__
x = Len()
Len = "xyz".__len__
y = 42 + Len()
Len = records.__len__
if Len() == 12:
print "twelve!"

Not only is that an especially ugly, confusing piece of code, it is also
counter-productive as you still have to do the method lookup every single
time.

The whole point of the optimization is avoiding 99999 attribute
lookups of the timeit loop. For a single call both times are
practically zero so the snippet above is just silly.
Taking the method lookup is an apple-and-oranges comparison. It is useful
to know for the times when you don't want an apple, you want an orange
(i.e. the tight loop example above).

This is an apples-and-apples comparison:
>>import timeit
>>timeit.Timer("Len = seq.__len__; Len()", "seq = range(12)").repeat()
[1.3109469413757324, 0.7687380313873291, 0.55280089378356934]>>timeit.Timer("len(seq)", "seq = range(12)").repeat()
For the record, the apples to apples way is to STORE_FAST len, because
what this does is compare the speed of LOAD_GLOBAL(len) to a
LOAD_ATTR, a STORE_FAST, and a LOAD_FAST. len() is still faster on
builtins when you do it "right":

C:\>python -m timeit -s "s=range(12);l=type([]).__len__" "l(s)"
1000000 loops, best of 3: 0.258 usec per loop

C:\>python -m timeit -s "l = len;s=range(12)" "l(s)"
10000000 loops, best of 3: 0.0994 usec per loop

This is absolutely apples to apples because exactly the same bytecodes
are being timed.

However, you can make the first faster by using an already bound
method. This saves some runtime cost inside the __len__ method, and it
saves a LOAD_FAST in the call. It's still slower than len(), by the
barest fraction of a second (I ran these a few dozen time each and the
difference, while tiny, was consistent - __len__ was always just over
a tenth of a usec, len() was always just under it).

C:\>python -m timeit -s "s=range(12);l=s.__len__" "l()"
10000000 loops, best of 3: 0.114 usec per loop
[0.60111594200134277, 0.5977931022644043, 0.59935498237609863]

The time to do the lookup and call the method is about 0.6 microseconds
whether you do it manually or let len() do it.

That assumes you know the internals of len(). Perhaps it does
something smarter for lists, or perhaps attribute lookup is faster at
the C level. I don't know, and that's exactly the point, I don't need
to know the internals to do the comparison of two callables.
Types implemented in C implement the sequence protocol as a struct of
function pointers, which len() derefs and calls directly, while
__len__ on the builtin is a Python boundmethod.

The speed difference will be reversed for types implemented in Python,
though. So now you know.
The logic behind the micro-optimization trick is to recognize when you
can avoid the cost of repeated method lookups by doing it once only. That
is not relevant to the question of whether len() should be a function or
a method.

No disagreement here; I didn't bring up performance and it's not at
all a reason I consider len() as a function to be a design mistake.
What I dispute is Neil's assertion that "len as a builtin can be
faster than len as an attribute" and bringing as evidence the timings
that include attribute lookups. That statement is just wrong;
comparing X to an attribute assumes you have the attribute in the
first place, you don't need to look it up.
And I don't think it's a design mistake for all the other reasons
mentioned, not because it's 6 thousands of a millisecond faster in a
microbenchmark.
Nov 1 '07 #34
On Oct 31, 6:29 pm, Steven D'Aprano <st...@REMOVE-THIS-
cybersource.com.auwrote:
On Wed, 31 Oct 2007 07:59:58 -0700, Carl Banks wrote:
Python considers len to be an operator for all intents and purposes.
Python chose to spell this operator like a regular function, but it
could easily have given a special syntax to the length operation (for
instance, $#x).

I hope you're not serious that $# would make a good operator.
If you happen to know where I borrowed it from, it would be pretty
evident that I wasn't being serious.
Carl Banks

Nov 1 '07 #35
On Oct 30, 1:30 am, George Sakkis <george.sak...@gmail.comwrote:
Having a builtin len() that calls the method __len__
seems (using your words) "not only foolish but wasteful".
But what about (for instance) having the bitwise not operator (^)
calling __bitwise_not__. Is that foolish and wasteful? Would a
hypothetical special syntax for len be foolish and wasteful.

All I'm trying to say here is that len is a built-in for a reason:
because Python considers len to be an operator. It's not inconsistent
design. It's not a defective spelling for a method. len was
deliberately given a status greater than method calls.
Carl Banks

Nov 1 '07 #36
On Wed, 31 Oct 2007 22:48:12 -0700, Carl Banks wrote:
>I hope you're not serious that $# would make a good operator.

If you happen to know where I borrowed it from, it would be pretty
evident that I wasn't being serious.
Ooh, now I'm curious.
--
Steven.
Nov 1 '07 #37
Steven D'Aprano <st***@REMOVE-THIS-cybersource.com.auwrote:
>On Wed, 31 Oct 2007 22:48:12 -0700, Carl Banks wrote:
>>I hope you're not serious that $# would make a good operator.

If you happen to know where I borrowed it from, it would be pretty
evident that I wasn't being serious.

Ooh, now I'm curious.
Seriously? You didn't know that $#x in perl returns the length of the
array @x, minus 1?
--
Tim Roberts, ti**@probo.com
Providenza & Boekelheide, Inc.
Nov 2 '07 #38
On Fri, 02 Nov 2007 03:40:59 +0000, Tim Roberts wrote:
Steven D'Aprano <st***@REMOVE-THIS-cybersource.com.auwrote:
>>On Wed, 31 Oct 2007 22:48:12 -0700, Carl Banks wrote:
>>>I hope you're not serious that $# would make a good operator.

If you happen to know where I borrowed it from, it would be pretty
evident that I wasn't being serious.

Ooh, now I'm curious.

Seriously? You didn't know that $#x in perl returns the length of the
array @x, minus 1?


I don't speak Perl. You know there are million of us who have managed to
avoid it.
--
Steven.
Nov 2 '07 #39
Steven D'Aprano <st****@REMOVE.THIS.cybersource.com.auwrites:
Seriously? You didn't know that $#x in perl returns the length of the
array @x, minus 1?
I don't speak Perl. You know there are million of us who have managed to
avoid it.
I used to use perl (though I was never an expert) and I didn't know that
$#x returns yada yada. Lucky me.
Nov 2 '07 #40
Steven D'Aprano a écrit :
On Fri, 02 Nov 2007 03:40:59 +0000, Tim Roberts wrote:
>Steven D'Aprano <st***@REMOVE-THIS-cybersource.com.auwrote:
>>On Wed, 31 Oct 2007 22:48:12 -0700, Carl Banks wrote:

I hope you're not serious that $# would make a good operator.
If you happen to know where I borrowed it from, it would be pretty
evident that I wasn't being serious.
Ooh, now I'm curious.
Seriously? You didn't know that $#x in perl returns the length of the
array @x, minus 1?

I don't speak Perl.
Nor do I, but such an ugly syntax is a sure hint !-)
Nov 2 '07 #41

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Steven Bethard | last post by:
So, as I understand it, in Python 3000, zip will basically be replaced with izip, meaning that instead of returning a list, it will return an iterator. This is great for situations like: zip(*)...
22
by: James H. | last post by:
Greetings! I'm new to Python and am struggling a little with "and" and "or" logic in Python. Since Python always ends up returning a value and this is a little different from C, the language I...
17
by: seb.haase | last post by:
Hi, Is it true that that "Python 3000" is dead ? Honestly I think that e.g. changing 5/2 to be 2.5 (instead of 2) would just break to much code :-( On the otherhand I'm using Python as "Matlab...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: marcoviolo | last post by:
Dear all, I would like to implement on my worksheet an vlookup dynamic , that consider a change of pivot excel via win32com, from an external excel (without open it) and save the new file into a...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.