By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,696 Members | 1,422 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,696 IT Pros & Developers. It's quick & easy.

language design question

P: n/a
I am comparing Python to a few other scripting languages, and used a simple
anagrams program as a sample.

I was surprised ast a few python features that did not work as I would
expect/wish; which caused less compact/expressive program styles that I
wanted - reverting to a FORTRAN like series of assignments.

For example,
- why is len() not a member function of strings? Instead one says len(w).

- Why doesn't sort() return a value?

This would allow things like:
key = '',join( list(word.lower().strip()).sort() )
instead:
key = ...
key.sort()
key = ...

- Another feature I assumed but it failed, is a nice default for
dictionaries, and more += like operations;
For example: to acculumate words in a dictionary -
dict[key] += [word]

Instead of:
mark[key] = mark.get(key,[]) + [word]

The former seems very intuitive, and clearer.
I am a bit used to the compactness and convenient defaults of Perl, which
would do this:
my $key = join '', sort(split(//, lc($word)));
push @{$anagrams{$key}}, $word

I am curious why these "obvious" conveniences are not present. :-)
Thansk for any context or insight.

Best,
Gregory

Perl is great, and

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Jul 9 '06 #1
Share this Question
Share on Google+
37 Replies


P: n/a
Gregory Guthrie wrote:
For example,
- why is len() not a member function of strings? Instead one says len(w).
Why would ``x.len()`` be any more convenient than ``len(x)``? Your
preference here seems pretty arbitrary.
- Why doesn't sort() return a value?

This would allow things like:
key = '',join( list(word.lower().strip()).sort() )
Use sorted():

key = ','.join(sorted(word.lower().strip()))

- Another feature I assumed but it failed, is a nice default for
dictionaries, and more += like operations;
For example: to acculumate words in a dictionary -
dict[key] += [word]
Get Python 2.5 and use collections.defaultdict:

Python 2.5a2 (trunk:46491M, May 27 2006, 14:43:55) [MSC v.1310 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>import collections
d = collections.defaultdict(int)
d['a'] += 5
d['b'] += 2
d
defaultdict(<type 'int'>, {'a': 5, 'b': 2})

STeVe
Jul 9 '06 #2

P: n/a
Gregory Guthrie a écrit :
I am comparing Python to a few other scripting languages, and used a simple
anagrams program as a sample.

I was surprised ast a few python features that did not work as I would
expect/wish; which caused less compact/expressive program styles that I
wanted - reverting to a FORTRAN like series of assignments.

For example,
- why is len() not a member function of strings? Instead one says len(w).
The member function of strings is __len__, which itself is called by
len() when passed a string. wrt/ why it is so, you'll have to ask to
someone more knowledgeable, but I seriously don't see what difference
it make in practice.
- Why doesn't sort() return a value?
If it's not in the FAQ, then it should - and the googling c.l.py
archives for this should give some relevant answers.
This would allow things like:
key = '',join( list(word.lower().strip()).sort() )
key = ''.join(list(sorted(word.lower().strip()))
- Another feature I assumed but it failed, is a nice default for
dictionaries, and more += like operations;
For example: to acculumate words in a dictionary -
dict[key] += [word]

Instead of:
mark[key] = mark.get(key,[]) + [word]
mark.setdefault(key, []).append(word)
The former seems very intuitive, and clearer.
and is much more error prone for few practical gain (assertion backed by
experience with languages allowing it).
I am a bit used to the compactness and convenient defaults of Perl, which
would do this:
my $key = join '', sort(split(//, lc($word)));
push @{$anagrams{$key}}, $word
key = ''.join(list(sorted(word.lower().strip()))
anagrams.setdefault(key, []).append(word)
I am curious why these "obvious" conveniences are not present. :-)
You said ?-)
Jul 9 '06 #3

P: n/a

Gregory Guthrie wrote:
I am comparing Python to a few other scripting languages, and used a simple
anagrams program as a sample.

I was surprised ast a few python features that did not work as I would
expect/wish; which caused less compact/expressive program styles that I
wanted - reverting to a FORTRAN like series of assignments.
<SNIP>
The former seems very intuitive, and clearer.
I am a bit used to the compactness and convenient defaults of Perl, which
would do this:
my $key = join '', sort(split(//, lc($word)));
push @{$anagrams{$key}}, $word

I am curious why these "obvious" conveniences are not present. :-)
Thansk for any context or insight.

Best,
Gregory

Perl is great, and
You might try looking for anagram programs written by Python
programmers and compare them to anagram programs written by peoplle
thatknow and use other languages.
That way you might get around the fact that Python is a unique language
with its own way of doing things. If you now one language and try and
apply its idioms to another then you are bound to think that the other
language is less good at solving prolblems in the first languages way.

Googling for Python Anagram, brought up
http://www.voidspace.org.uk/python/n...l#demo-version

maybe you should look at the source code to nanagram for comparison.

- Paddy.

Jul 9 '06 #4

P: n/a

"Gregory Guthrie" <gu*****@mum.eduwrote in message
news:11**************@sp6iad.superfeed.net...
- why is len() not a member function of strings? Instead one says
len(w).
Consider
>>map(len, ('abc', (1,2,3), [1,2], {1:2}))
[3, 3, 2, 1]

Now try to rewrite this using methods (member functions).
- Why doesn't sort() return a value?
Because it is an in-place mutation method and Guido decided that such
methods should return None rather that the mutated object to lessen bugs.
It is a tradeoff that has been debated ever since ;-)
For example: to acculumate words in a dictionary -
dict[key] += [word]
This expands to dict[key] = dict[key] + [word]. When the latter is valid
(when dict[key] exists and is a list), then the former works fine also.
>>k='a'
d = {k:[]}
d[k]+=['b']
d
{'a': ['b']}

I presume the new-in-2.5 default dicts will do the same, and also work when
the key does not exist and the default is a list.

Terry Jan Reedy

Jul 9 '06 #5

P: n/a
Terry Reedy wrote:
Consider
>>>map(len, ('abc', (1,2,3), [1,2], {1:2}))
[3, 3, 2, 1]

Now try to rewrite this using methods (member functions).
[a.len() for a in ('abc', (1,2,3), [1,2], {1:2})]

--
--OKB (not okblacke)
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is
no path, and leave a trail."
--author unknown
Jul 9 '06 #6

P: n/a
"Terry Reedy" <tj*****@udel.eduwrites:
Consider
>map(len, ('abc', (1,2,3), [1,2], {1:2}))
[3, 3, 2, 1]

Now try to rewrite this using methods (member functions).
[x.len() for x in ('abc', (1,2,3), [1,2], {1:2})]
- Why doesn't sort() return a value?

Because it is an in-place mutation method and Guido decided that such
methods should return None rather that the mutated object to lessen bugs.
It is a tradeoff that has been debated ever since ;-)
Nah, we have sorted() now, a functionalista victory ;-)
I presume the new-in-2.5 default dicts will do the same, and also work when
the key does not exist and the default is a list.
Man, it's hard to keep track of these new features. Default dicts do
sound like a good addition; I've used those d.setdefault/d.get idioms
way too often.
Jul 9 '06 #7

P: n/a
On Sun, 09 Jul 2006 12:19:13 -0500, Gregory Guthrie wrote:
I am comparing Python to a few other scripting languages, and used a simple
anagrams program as a sample.

I was surprised ast a few python features that did not work as I would
expect/wish; which caused less compact/expressive program styles that I
wanted - reverting to a FORTRAN like series of assignments.

For example,
- why is len() not a member function of strings? Instead one says len(w).
Length is an obvious property of any one-dimensional non-scalar, not just
strings. As such, it makes sense to have a length function that takes an
argument. As a design decision, it could go either way, but early
Python wasn't fully object-oriented. If Guido was designing Python
from scratch today, who knows whether he'd still make len a function?
- Why doesn't sort() return a value?
Because if you have a 100 MB list of objects which you want to sort, why
go to the significant expense of making a sorted copy only to throw the
original away?

In general, Python never copies data unless you explicitly tell it too. If
you want to keep the original, unsorted list around, you need to make a
copy of it explicitly.

This would allow things like:
key = '',join( list(word.lower().strip()).sort() )
instead:
key = ...
key.sort()
key = ...
One liners are over-rated.
- Another feature I assumed but it failed, is a nice default for
dictionaries, and more += like operations;
What default should this dictionary have?

{'key1' = 'alpha', 'key2' = 1, 'key3' = [4, 7, 3]}

Should it be '', 0, [], None or something else? Be prepared to justify
why your choice is suitable not just for *this* dictionary, but for *all*
dictionaries.

I am curious why these "obvious" conveniences are not present. :-)
Thansk for any context or insight.

Perhaps the best way to understand the Python philosophy is to call up an
interpreter and execute "import this" at the prompt.
--
Steven.

Jul 9 '06 #8

P: n/a
On Sun, 09 Jul 2006 22:45:53 +0000, OKB (not okblacke) wrote:
Terry Reedy wrote:
>Consider
>>>>map(len, ('abc', (1,2,3), [1,2], {1:2}))
[3, 3, 2, 1]

Now try to rewrite this using methods (member functions).

[a.len() for a in ('abc', (1,2,3), [1,2], {1:2})]
Did you actually try that?
>>'abc'.len()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'str' object has no attribute 'len'

In any case, list comprehensions are a recent (version 2.2 I think?)
addition to Python. You have to think about the functionality
available back in the days when the decision to make len() a function was
made, not based on what functionality is available a decade later.
--
Steven.

Jul 9 '06 #9

P: n/a
Steven D'Aprano wrote:
On Sun, 09 Jul 2006 22:45:53 +0000, OKB (not okblacke) wrote:
>Terry Reedy wrote:
>>Consider
>map(len, ('abc', (1,2,3), [1,2], {1:2}))
[3, 3, 2, 1]

Now try to rewrite this using methods (member functions).
[a.len() for a in ('abc', (1,2,3), [1,2], {1:2})]

Did you actually try that?
He was answering a hypothetical. He wasn't suggesting that was valid
syntax today.

--
Erik Max Francis && ma*@alcyone.com && http://www.alcyone.com/max/
San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis
Don't try to confuse me with the facts.
-- Bill McNeal
Jul 10 '06 #10

P: n/a
Steven D'Aprano <st***@REMOVETHIScyber.com.auwrites:
Now try to rewrite this using methods (member functions).
[a.len() for a in ('abc', (1,2,3), [1,2], {1:2})]

Did you actually try that?
No of course not. It's in a hypothetical python where .len() is a
class operation instead of a global function.
In any case, list comprehensions are a recent (version 2.2 I think?)
addition to Python. You have to think about the functionality
available back in the days when the decision to make len() a function was
made, not based on what functionality is available a decade later.
Correct, so the answer to the OP's question might well be "it's that
way because of historical accidents".
Jul 10 '06 #11

P: n/a
Steven D'Aprano <st***@REMOVETHIScyber.com.auwrites:
Length is an obvious property of any one-dimensional non-scalar, not just
strings. As such, it makes sense to have a length function that takes an
argument. As a design decision, it could go either way, but early
Python wasn't fully object-oriented. If Guido was designing Python
from scratch today, who knows whether he'd still make len a function?
There could be a multidimensional variant which gives the shape of an
array, like the APL rho operator. RMS once wrote a song about it
(tune of "Row, row, row your boat"):

Rho rho rho of x, always equals 1,
Rho's dimension, rho rho rank, APL is fun!
- Why doesn't sort() return a value?

Because if you have a 100 MB list of objects which you want to sort, why
go to the significant expense of making a sorted copy only to throw the
original away?
..sort() could sort in place and return the sorted list instead of returning None.
In general, Python never copies data unless you explicitly tell it too. If
you want to keep the original, unsorted list around, you need to make a
copy of it explicitly.
The convention actually is that mutating operations like .sort()
return None, which supposedly helps avoid certain types of errors.
But it leads to tedious code, thus the addition of sorted(). sorted()
of course has the nice property of being able to operate on arbitrary
sequences, which was one of the (valid) justifications for making it a
function.

The Lisp convention would be to name the function "nsort" (like
nreverse, nconc, etc.) where the "n" signifies that the operation is
in-place. The Scheme convention is to suffix with "!", like "set!",
"sort!", "reverse!", and so forth.
This would allow things like:
key = '',join( list(word.lower().strip()).sort() )
instead:
key = ...
key.sort()
key = ...

One liners are over-rated.
...
Perhaps the best way to understand the Python philosophy is to call up an
interpreter and execute "import this" at the prompt.
"Beautiful is better than ugly".
Jul 10 '06 #12

P: n/a
Bruno Desthuilliers <bd*****************@free.quelquepart.frwrote:
...
This would allow things like:
key = '',join( list(word.lower().strip()).sort() )

key = ''.join(list(sorted(word.lower().strip()))
No need to make yet another list here (also, I think each of you omitted
a needed closed-paren!-) -- you could just use:

key = ''.join(sorted(word.lower().strip()))

- Another feature I assumed but it failed, is a nice default for
dictionaries, and more += like operations;
For example: to acculumate words in a dictionary -
dict[key] += [word]

Instead of:
mark[key] = mark.get(key,[]) + [word]

mark.setdefault(key, []).append(word)
setdefault was a worthy experiment, but it works rather clumsily in real
life -- most of us are back to splitting such "multidict assignments"
into two statements, such as:
if key in mark: mark[key].append(word)
else: mark[key] = [word]

Fortunately, 2.5's collections.defaultdict makes it pretty again (and
VASTLY more general than the one and only "nice default" the OP is
wishing for;-).
Alex
Jul 10 '06 #13

P: n/a
Steven Bethard wrote:
Gregory Guthrie wrote:
>For example,
- why is len() not a member function of strings? Instead one says
len(w).

Why would ``x.len()`` be any more convenient than ``len(x)``? Your
preference here seems pretty arbitrary.
-- Perhaps;
but having all standard operations as a method seems more regular (to
me), and allows a simple chained operation format of a series of method
calls, instead of alternating prefix function calls, and post-fix method
invocations; e.g.
x.lower().strip().toList().sort().join()
seems cleaner and simpler than the usage below, where the pre/post
alternation is visually more complex.

I think the mix of OO like methods, and global functions, is not ideal.
>
> - Why doesn't sort() return a value?

This would allow things like:
key = '',join( list(word.lower().strip()).sort() )


Use sorted():

key = ','.join(sorted(word.lower().strip()))
-- Thanks!
(Is the comma in ',' just a typo?)
>
> - Another feature I assumed but it failed, is a nice default for
dictionaries, and more += like operations;
For example: to acculumate words in a dictionary -
dict[key] += [word]


Get Python 2.5 and use collections.defaultdict:
-- Great, thanks.
>
Python 2.5a2 (trunk:46491M, May 27 2006, 14:43:55) [MSC v.1310 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>import collections
>>d = collections.defaultdict(int)
>>d['a'] += 5
>>d['b'] += 2
>>d
defaultdict(<type 'int'>, {'a': 5, 'b': 2})

STeVe

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Jul 10 '06 #14

P: n/a

"OKB (not okblacke)" <br************@NObrenSPAMbarn.netwrote in message
news:Xn*****************@81.174.50.80...
Terry Reedy wrote:
>Consider
>>>>map(len, ('abc', (1,2,3), [1,2], {1:2}))
[3, 3, 2, 1]

Now try to rewrite this using methods (member functions).

[a.len() for a in ('abc', (1,2,3), [1,2], {1:2})]
What I meant and should have said more specificly:
try rewriting the map call or any similar call of a 2nd-order function as
a call of the same function using methods. Map here stands for the class
of functions that take a function as an arg and apply it to an unknown
(until runtime) type or to a mixture of types. Its particular replacement
(not rewrite, as I meant the word) does not apply to the generic pattern.

This can be done (since 2.2) either with or without using the operater
module. Until 2.2, many builtin classes, including strings, tuples, and
number, did not have visible methods.

The underlying answer to the original question is that while Pyt;hon is
object-based, it is not strictly OO but is intentionally multiparadigmatic
and will remain so. For instance, no one will be forced to replace the
procedural expression 'a+b' with the strict OO equivalent 'a .__add__(b)'.
But anyone is free to do so in their own code, just as with ob.__len__()
for len(ob).

Terry Jan Reedy

Jul 10 '06 #15

P: n/a
guthrie wrote:
Steven Bethard wrote:
>Why would ``x.len()`` be any more convenient than ``len(x)``? Your
preference here seems pretty arbitrary.
-- Perhaps;
but having all standard operations as a method seems more regular (to
me), and allows a simple chained operation format of a series of method
calls, instead of alternating prefix function calls, and post-fix method
invocations; e.g.
x.lower().strip().toList().sort().join()
seems cleaner and simpler than the usage below, where the pre/post
alternation is visually more complex.
I think the mix of OO like methods, and global functions, is not ideal.
The advantage of a functional form over a method shows up when you write
a function that works on a variety of different types. Below are
implementations of "list()", "sorted()" and "join()" that work on any
iterable and only need to be defined once::

def list(iterable):
result = []
for item in iterable:
result.append(item)
return result

def sorted(iterable):
result = list(iterable)
result.sort()
return result

def join(iterable):
# this is more efficient in C, where the string's buffer can be
# pre-allocated before iterating through the loop.
result = ''
for item in iterable:
result += item
return result

Now, by providing these as functions, I only have to write them once,
and they work on *any* iterable, including some container object that
you invent tomorrow.

If everything were methods, when you invented your container object
tomorrow, you'd have to reimplement these methods on your class. (Or
we'd have to introduce a Container class to provide them, and everyone
would have to inherit from that if they wanted to define a container.)
>> - Why doesn't sort() return a value?

This would allow things like:
key = '',join( list(word.lower().strip()).sort() )

Use sorted():

key = ','.join(sorted(word.lower().strip()))
-- Thanks!
(Is the comma in ',' just a typo?)
No, the comma puts a comma between each item. I wasn't sure whether the
comma in your original was a typo for ''. or for ','. Of course if you
don't want the comma between each item, you should just use ''

STeVe
Jul 10 '06 #16

P: n/a
Terry Reedy wrote:
"Gregory Guthrie" <gu*****@mum.eduwrote in message
news:11**************@sp6iad.superfeed.net...
> - why is len() not a member function of strings? Instead one says
len(w).

Consider
>>>map(len, ('abc', (1,2,3), [1,2], {1:2}))
[3, 3, 2, 1]

Now try to rewrite this using methods (member functions).
For all the doubters out there, here's an example you can't really
rewrite with a list comprehension::
>>sorted(['aaa', 'bb', 'c'])
['aaa', 'bb', 'c']
>>sorted(['aaa', 'bb', 'c'], key=len)
['c', 'bb', 'aaa']

If len() were a method of string objects, you could try using the
unbound method and writing this as::
>>sorted(['aaa', 'bb', 'c'], key=str.len)
['c', 'bb', 'aaa']

But then your code would break on lists that weren't strings.

STeVe
Jul 10 '06 #17

P: n/a
Many thanks; great information.

Best,
Gregory

Steven Bethard wrote:
guthrie wrote:
>Steven Bethard wrote:
>>Why would ``x.len()`` be any more convenient than ``len(x)``? Your
preference here seems pretty arbitrary.

-- Perhaps;
but having all standard operations as a method seems more regular (to
me), and allows a simple chained operation format of a series of
method calls, instead of alternating prefix function calls, and
post-fix method invocations; e.g.
x.lower().strip().toList().sort().join()
seems cleaner and simpler than the usage below, where the pre/post
alternation is visually more complex.
I think the mix of OO like methods, and global functions, is not ideal.


The advantage of a functional form over a method shows up when you write
a function that works on a variety of different types. Below are
implementations of "list()", "sorted()" and "join()" that work on any
iterable and only need to be defined once::

def list(iterable):
result = []
for item in iterable:
result.append(item)
return result

def sorted(iterable):
result = list(iterable)
result.sort()
return result

def join(iterable):
# this is more efficient in C, where the string's buffer can be
# pre-allocated before iterating through the loop.
result = ''
for item in iterable:
result += item
return result

Now, by providing these as functions, I only have to write them once,
and they work on *any* iterable, including some container object that
you invent tomorrow.

If everything were methods, when you invented your container object
tomorrow, you'd have to reimplement these methods on your class. (Or
we'd have to introduce a Container class to provide them, and everyone
would have to inherit from that if they wanted to define a container.)
>>> - Why doesn't sort() return a value?

This would allow things like:
key = '',join( list(word.lower().strip()).sort() )
Use sorted():

key = ','.join(sorted(word.lower().strip()))

-- Thanks!
(Is the comma in ',' just a typo?)


No, the comma puts a comma between each item. I wasn't sure whether the
comma in your original was a typo for ''. or for ','. Of course if you
don't want the comma between each item, you should just use ''

STeVe

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Jul 10 '06 #18

P: n/a
Good point, thanks.

But if (as I proposed..!) the user interface is better if presented as a
method. one could porovide convenience methods which would then
interface to these underlying library functions; yes?

So the main datatype classes could support such a method style, and just
layer on top of the library.

Anyway, I get your point, thanks.

Greg

Steven Bethard wrote:
guthrie wrote:
>Steven Bethard wrote:
>>Why would ``x.len()`` be any more convenient than ``len(x)``? Your
preference here seems pretty arbitrary.

-- Perhaps;
but having all standard operations as a method seems more regular (to
me), and allows a simple chained operation format of a series of
method calls, instead of alternating prefix function calls, and
post-fix method invocations; e.g.
x.lower().strip().toList().sort().join()
seems cleaner and simpler than the usage below, where the pre/post
alternation is visually more complex.
I think the mix of OO like methods, and global functions, is not ideal.


The advantage of a functional form over a method shows up when you write
a function that works on a variety of different types. Below are
implementations of "list()", "sorted()" and "join()" that work on any
iterable and only need to be defined once::

def list(iterable):
result = []
for item in iterable:
result.append(item)
return result

def sorted(iterable):
result = list(iterable)
result.sort()
return result

def join(iterable):
# this is more efficient in C, where the string's buffer can be
# pre-allocated before iterating through the loop.
result = ''
for item in iterable:
result += item
return result

Now, by providing these as functions, I only have to write them once,
and they work on *any* iterable, including some container object that
you invent tomorrow.

If everything were methods, when you invented your container object
tomorrow, you'd have to reimplement these methods on your class. (Or
we'd have to introduce a Container class to provide them, and everyone
would have to inherit from that if they wanted to define a container.)
STeVe

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Jul 10 '06 #19

P: n/a
Steven Bethard wrote:
The advantage of a functional form over a method shows up when you write
a function that works on a variety of different types. Below are
implementations of "list()", "sorted()" and "join()" that work on any
iterable and only need to be defined once::

def list(iterable):
result = []
for item in iterable:
result.append(item)
return result

def sorted(iterable):
result = list(iterable)
result.sort()
return result

def join(iterable):
# this is more efficient in C, where the string's buffer can be
# pre-allocated before iterating through the loop.
result = ''
for item in iterable:
result += item
return result

Now, by providing these as functions, I only have to write them once,
and they work on *any* iterable, including some container object that
you invent tomorrow.

If everything were methods, when you invented your container object
tomorrow, you'd have to reimplement these methods on your class. (Or
we'd have to introduce a Container class to provide them, and everyone
would have to inherit from that if they wanted to define a container.)
could you get the same result by putting these methods in base class object that
everything subclasses? then you wouldn't have to reimplement these methods on
your class either, right? i'm not arguing for one method or the other. just
curious about the difference.

bryan

Jul 10 '06 #20

P: n/a
Alex Martelli wrote:
Bruno Desthuilliers <bd*****************@free.quelquepart.frwrote:
...
>> This would allow things like:
key = '',join( list(word.lower().strip()).sort() )

key = ''.join(list(sorted(word.lower().strip()))


No need to make yet another list here (also, I think each of you omitted
a needed closed-paren!-)
Possibly
-- you could just use:

key = ''.join(sorted(word.lower().strip()))
Yes, of course - too quick answer, half-backed answer...

(snip)
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 10 '06 #21

P: n/a
Steven Bethard wrote:
Terry Reedy wrote:
>"Gregory Guthrie" <gu*****@mum.eduwrote in message
news:11**************@sp6iad.superfeed.net...
>> - why is len() not a member function of strings? Instead one says
len(w).


Consider
>>>>map(len, ('abc', (1,2,3), [1,2], {1:2}))

[3, 3, 2, 1]

Now try to rewrite this using methods (member functions).
map(lambda obj: obj.__len__(), ('abc', (1,2,3), [1,2], {1:2}))
For all the doubters out there, here's an example you can't really
rewrite with a list comprehension::
>>sorted(['aaa', 'bb', 'c'])
['aaa', 'bb', 'c']
>>sorted(['aaa', 'bb', 'c'], key=len)
['c', 'bb', 'aaa']
Nope, but it still doesn't require len() being a function
If len() were a method of string objects, you could try using the
unbound method and writing this as::
>>sorted(['aaa', 'bb', 'c'], key=str.len)
['c', 'bb', 'aaa']

But then your code would break on lists that weren't strings.
sorted(['aaa', 'bb', 'c'], key=lambda obj: obj.__len__())

Note that in both cases, my lambda is mostly a reimplementation of len()
- and as far as I'm concerned, len() is quite ok...

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 10 '06 #22

P: n/a
Steven Bethard <st************@gmail.comwrites:
If len() were a method of string objects, you could try using the
unbound method and writing this as::
>>sorted(['aaa', 'bb', 'c'], key=str.len)
['c', 'bb', 'aaa']

But then your code would break on lists that weren't strings.
sorted(['aaa', 'bb', 'c'], key=lambda x: x.len())
Jul 10 '06 #23

P: n/a
guthrie wrote:
Good point, thanks.

But if (as I proposed..!) the user interface is better if presented as a
method. one could porovide convenience methods which would then
interface to these underlying library functions; yes?
Actually, and AFAIK, len(obj) = lambda obj : obj.__len__().

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 10 '06 #24

P: n/a
"guthrie" wrote:
But if (as I proposed..!) the user interface is better if presented as a
method. one could porovide convenience methods which would then
interface to these underlying library functions; yes?
but if it isn't? and why this obsession with superficial syntax details? there's
a lot more to a language than what standard syntax it uses for trivial things...

</F>

Jul 10 '06 #25

P: n/a
Ant
- why is len() not a member function of strings? Instead one says len(w).
Coming from a Java background, I also thought this a weird setup.
However IMHO there is another good reason to have len(obj) as we do in
Python: it helps to enforce some sort of uniformity across code.

If I want to find out the length of some object, then I know to try
len(obj). If it were merely convention that objects had a obj.len()
method, then some objects would be written to conform to this. As
things stand, it is common knowledge that len(obj) returns the length
of an object, and that the way to give you own objects the same
functionality is to give it a __len__() method.

The alternative of having a obj.len() function as a convention is less
compelling to use - if the users are reading your api, why not call the
method size() or magnitude() or just give it a length attribute, and
suddenly objects become less polymorphic as far as writing generic
functions is concerned.

Look at Java's Standard API for examples. An array has a length
attribute. A String has a length() method. Collections have a size()
method. Buffer objects have a capacity() method. One of Python's
strengths is that I can write a generic method:

def printSize(obj): print "The size of this object is %d" % len(obj)

If we had a Java-like situation we'd have to test for different object
types before deciding on which method/attribute to call:

def printSize(obj):
len = None
if type(obj) == str: len = obj.len()
elif type(obj) == Buffer: len = obj.capacity()
...
print "The size of this object is %d" % len

Just my view on the matter :-)

Jul 10 '06 #26

P: n/a
>>>>Bruno Desthuilliers <on***@xiludom.gro(BD) wrote:
>BDActually, and AFAIK, len(obj) = lambda obj : obj.__len__().
You mean: len = lambda obj : obj.__len__().
--
Piet van Oostrum <pi**@cs.uu.nl>
URL: http://www.cs.uu.nl/~piet [PGP 8DAE142BE17999C4]
Private email: pi**@vanoostrum.org
Jul 10 '06 #27

P: n/a
Piet van Oostrum wrote:
>>>>>>Bruno Desthuilliers <on***@xiludom.gro(BD) wrote:

>>BDActually, and AFAIK, len(obj) = lambda obj : obj.__len__().


You mean: len = lambda obj : obj.__len__().
yes, of course - not enough caffein, I guess...

Thanks
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'on***@xiludom.gro'.split('@')])"
Jul 10 '06 #28

P: n/a
Steven Bethard a écrit :
The advantage of a functional form over a method shows up when you write
a function that works on a variety of different types. Below are
implementations of "list()", "sorted()" and "join()" that work on any
iterable and only need to be defined once::

[... skipped ...]

Now, by providing these as functions, I only have to write them once,
and they work on *any* iterable, including some container object that
you invent tomorrow.
Yep. Rubyphiles would probably define these 3 methods in a "module"
Iterable and "mix" it in their brand new container classes.
These classes then automatically have list, sorted and join *as
methods*.

Guess you could use this kind of trick in Python if you can live with
heavy *and* implicit surgery of the inheritance chain ;)

Cheers,

SB

Jul 10 '06 #29

P: n/a
Bryan wrote:
could you get the same result by putting these methods in base
class object that everything subclasses?
and how do you make sure that everything subclasses this base class ?

</F>

Jul 10 '06 #30

P: n/a
Bryan wrote:
Steven Bethard wrote:
>The advantage of a functional form over a method shows up when you
write a function that works on a variety of different types. Below are
implementations of "list()", "sorted()" and "join()" that work on any
iterable and only need to be defined once::

def list(iterable):
result = []
for item in iterable:
result.append(item)
return result

def sorted(iterable):
result = list(iterable)
result.sort()
return result

def join(iterable):
# this is more efficient in C, where the string's buffer can be
# pre-allocated before iterating through the loop.
result = ''
for item in iterable:
result += item
return result

Now, by providing these as functions, I only have to write them once,
and they work on *any* iterable, including some container object that
you invent tomorrow.

If everything were methods, when you invented your container object
tomorrow, you'd have to reimplement these methods on your class. (Or
we'd have to introduce a Container class to provide them, and everyone
would have to inherit from that if they wanted to define a container.)

could you get the same result by putting these methods in base class
object that everything subclasses? then you wouldn't have to
reimplement these methods on your class either, right?
Well, you don't want to put them on object, because not everything is a
container (e.g. you don't want the sorted() method on ints). So you
have to put them on some subclass of object and then require everyone
who every creates a container class to inherit from that object. Python
generally frowns upon required inheritance from a particular type, but
at the same time, it does provide things like UserDict.DictMixin for
something very much along these lines. But I don't think too many folks
want to *require* that every dict-like object inherit from DictMixin.

STeVe
Jul 10 '06 #31

P: n/a
Paul Rubin wrote:
Steven Bethard <st************@gmail.comwrites:
>If len() were a method of string objects, you could try using the
unbound method and writing this as::
> >>sorted(['aaa', 'bb', 'c'], key=str.len)
['c', 'bb', 'aaa']

But then your code would break on lists that weren't strings.

sorted(['aaa', 'bb', 'c'], key=lambda x: x.len())
Of course, but all you're doing with the lambda is creating the len()
function.

STeVe
Jul 10 '06 #32

P: n/a
Terry Reedy wrote:
"OKB (not okblacke)" <br************@NObrenSPAMbarn.netwrote in message
[...]
>
The underlying answer to the original question is that while Pyt;hon is
object-based, it is not strictly OO but is intentionally multiparadigmatic
and will remain so. For instance, no one will be forced to replace the
procedural expression 'a+b' with the strict OO equivalent 'a .__add__(b)'.
But anyone is free to do so in their own code, just as with ob.__len__()
for len(ob).
In other words: "because it is".

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Jul 10 '06 #33

P: n/a
Fredrik Lundh wrote:
Bryan wrote:
>could you get the same result by putting these methods in base
class object that everything subclasses?

and how do you make sure that everything subclasses this base class ?

</F>
in this hypothetical case, i was assuming len() would be put in object and every
class subclasses object implicitly or explicitly (ie, new style classes only).
if it was done that way, would len(obj) == obj.len() in all cases?
bryn
Jul 11 '06 #34

P: n/a
"Bryan" wrote:
>and how do you make sure that everything subclasses this base class ?

in this hypothetical case, i was assuming len() would be put in object and every
class subclasses object implicitly or explicitly (ie, new style classes only).
if it was done that way, would len(obj) == obj.len() in all cases?
why should *everything* be forced to have a length ?

</F>

Jul 11 '06 #35

P: n/a
Bryan wrote:
Fredrik Lundh wrote:
>>Bryan wrote:

>>>could you get the same result by putting these methods in base
class object that everything subclasses?

and how do you make sure that everything subclasses this base class ?

</F>

in this hypothetical case, i was assuming len() would be put in object and every
class subclasses object implicitly or explicitly (ie, new style classes only).
if it was done that way, would len(obj) == obj.len() in all cases?
>>isinstance(1, object)
True

What's 1 . len() ?

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Jul 11 '06 #36

P: n/a
>>isinstance(1, object)
True

What's 1 . len() ?
That's easy!
since 1 is actually syntactic sugar for set([set([])]), clearly 1.len()
== 1.

;-)
v.
(actually, make that frozenset([frozenset([])])...)

Jul 11 '06 #37

P: n/a
Fredrik Lundh wrote:
"Bryan" wrote:
>>and how do you make sure that everything subclasses this base class ?
in this hypothetical case, i was assuming len() would be put in object and every
class subclasses object implicitly or explicitly (ie, new style classes only).
if it was done that way, would len(obj) == obj.len() in all cases?

why should *everything* be forced to have a length ?

</F>
good point. you're right, everything should not have to be forced to have a
length. i thought ruby did something like putting length functionality in their
highest level base class. then subclasses would either inherit it or could
modify it in their own class. my coworker who knows ruby complains about
python's len(obj) too. so i assumed ruby implements this in their equivalent
base object class. i just briefly searched the ruby docs, but i can't seem to
find it. if it is done this way in ruby, then i wonder what happens what
obj.length would return for objects that you would not normally associate as
having a length, such as what steve holden mentioned 1.length.

bryan

Jul 11 '06 #38

This discussion thread is closed

Replies have been disabled for this discussion.