General question about Python design goals

  • Thread starter Christoph Zwerschke
  • Start date
C

Christoph Zwerschke

Mike said:
But a programming language (or UI) is not just a collection of syntax
and and interfaces - it's an implementation. You need to keep in mind
that "practicality beats purity". If following POLA makes the
implementation an order of magnitude slower or larger, then you don't
follow POLA - at least until you can do it without that cost.

I do not deny this. As an example, if tuples can be used as keys of
dicts, you might first naively assume that lists could also work. This
is not the case for practicality (performance) reasons and because it
would be difficult or impossible to guarantee the uniqueness of keys. In
this case, POLA is overruled by other goals or inherent necessities.

But that does not mean that POLA in itself is not an important guiding
principle for programming languages (or UI).

-- Christoph
 
B

Bengt Richter

From what's been said here before, the doc committers aren't picky
about getting patches. That requires learning whatever doc format they
use, and they understand that that's a pretty hefty burden for a one
or two-paragraph tweak on the documentation. So submitting docs in
English works. Submitting patches works *better*, but not doing so
doesn't consign your suggestions to oblivion.
Ok, sounds reasonable.
BTW, no opinion on iter as a type harboring sequence-applicable methods? ;-)

Regards,
Bengt Richter
 
F

Fredrik Lundh

Steve said:
Yes, but that's the academic world, and bike sheds are a real-world
requirement so they will tend to be ignored indefinitely.

on the other hand, it's also possible that there are perfectly usable ways
to keep bikes and bike seats dry where Christoph works, but that he prefers
not to use them because they're violating some design rule.

(this is related to the drain pipe effect, where engineers spend endless
hours talking about how to make it easier to climb the drain pipe, while
everyone uses the stairs...)

</F>
 
S

Sibylle Koczian

Peter said:
Is that really the translation? "too lazy to search for searching"?
What does that mean?

Google translate doesn't help... here's it's rather comical attempt:

"Who order holds is only to putrid for looking for - a genius grasps the
chaos"

Automated translation in a nutshell.
 
B

Bengt Richter

IMO that is a non-sequitur, because that makes what is good or bad
design dependand on the language used.

If I have a design that seems to require tuples with a count method,
then wether that is a good or bad design doesn't depend on
whether or not python allows that or not.
No, but if your requirement is to count __eq__ - matching items in a
tuple, maybe your sense of orthogonality ought to abstract out the
sequence aspect in some other way than seeing it as a seeming method
requirement for tuple. A tuple.count method has implications about
attribute access to a special object, tuple, which then you have
to deal with for every new object you introduce, unless you want to
inherit it from object, but that means object becomes a
mega swiss army knife in short order.

So IMO the thing is not to ask for a specific solution like "why
not a count method for tuples?" You'll just get answers to that literal
question, with some elaborations. Instead, if you put it in the form
of what your general requirement really is (I'm guessing ;-) which I
assume is to be able to apply list count method _functionality_ to
anything which quacks like a list, including tuples etc. In short,
anything iterable.

Now the problem is to bring program and data together with some
spelling in python. data.method() is certainly one spelling, but
so is method(data). You gain something either way. The first allows
you to associate the method and data without executing the method, i.e.,
data.method is a bound method object that has the data-method association
built in, and it can be passed around. method(data) does the call right
away and uses a diferent name space search path to find method, and is
not necessarily associated with type(data). To ask for common methods
for all objects that exhibit some similar aspect is to entangle their
types in some way or to duplicate stuff. Sometimes it's fine to
derive from a common base etc., but

why not a built-in count function that does something like (untested)

def count(obj, match_item, eq=operator.eq):
return sum(1 for item in iter(obj) if eq(item, match_item))

which would give a little flexibility about eq comparison as well as
wide applicability to any sequence? index too (untested)

def index(obj, match_item, eq=operator.eq):
try: return (i for i, item in enumerate(obj) if eq(item, match_item)).next()
except StopIteration: raise ValueError('index(seq, item): item not in seq')

why doesn't list have a find like str? ;-)

def find(obj, match_item, eq=operator.eq):
try: return (i for i, item in enumerate(obj) if eq(item, match_item)).next()
except StopIteration: return -1

One could create an alternate spelling for obj.count(thing) using the count function above.
You can spell it now as

count.__get__(obj, type(obj))(thing)

if you want to duplicate the effect of having the count function retrieved from type(obj)
as if it were a method defined there. Or you can spell it

count(obj)

which doesn't seem too bad ;-)
But now the problem is cluttering the __builtins__ space. So maybe it would be
better to write
from sequence_goodies import count
...
count(obj)

Do you really want a count method for tuple? Or is that maybe not as clean is
it seemed? All the issues aren't usually immediatly apparent, so IMO the more
we focus on abstract functionality desired, the more likely we will get
helpful solution ideas for a menu of choices, and avoid prematurely discussing
whether we should have pumpkin pie with or without whipped cream, when finally
we might all like strawberries and cream better, if someone had thought of it.

Regards,
Bengt Richter
 
C

Christoph Zwerschke

Fredrik said:
on the other hand, it's also possible that there are perfectly usable ways
to keep bikes and bike seats dry where Christoph works, but that he prefers
not to use them because they're violating some design rule.

Depends on how you understand "perfectly usable." My collegue always
carries his expensive racing bike to our office in the 3rd floor out of
fear it may get wet or stolen. But I think this is not very convenient
and I want to avoid discussions with our boss about skid marks on the
carpet and things like that. Probably that collegue would not complain
as well if he had to cast tuples to lists for counting items - you see,
people are different ;-)

-- Christoph
 
P

Paul Rubin

Mike Meyer said:
But a programming language (or UI) is not just a collection of syntax
and and interfaces - it's an implementation. You need to keep in mind
that "practicality beats purity".

An awful lot of the time in this newsgroup, "practicality beats
purity" translates as "the programmer can just be a lazy slob".
If following POLA makes the implementation an order of magnitude
slower or larger, then you don't follow POLA - at least until you
can do it without that cost.

If following POLA costs that much, at least in the kinds of examples
we talk about all the time here, something is probably wrong with the
implementation (or the design) to begin with.
 
M

Mike Meyer

Paul Rubin said:
An awful lot of the time in this newsgroup, "practicality beats
purity" translates as "the programmer can just be a lazy slob".

You post that as if it were a bad thing.
If following POLA costs that much, at least in the kinds of examples
we talk about all the time here, something is probably wrong with the
implementation (or the design) to begin with.

True, but not constructive. Knowing that something is wrong is
easy. Diagnosing the problem is harder. Curing it is even harder. And
unti you get to that last step, you haven't done anything to improve
the situation.

<mike
 
P

Paul Rubin

Mike Meyer said:
You post that as if it were a bad thing.

Yes. The idea of using a program that someone else wrote, is that
they do the work so I don't have to. If their doing less work means
that I have to do more, the program isn't as good as it might be.

A program like Python intended for wide distribution and use by large
numbers of people whose needs aren't known in advance, should do as
much to help its users as development resources allow.

Are you familiar with R. Gabriel's piece "Worse is better"? That's
not what I see "practicality beats purity" as being intended to mean.
True, but not constructive. Knowing that something is wrong is
easy. Diagnosing the problem is harder. Curing it is even harder.

Look at the list.count() example at the start of this thread.
Diagnosing it isn't hard. Curing it isn't hard. It doesn't bloat
Python by an order of magnitude. A suitably factored implementation
might handle lists and strings with the exact same code and not incur
any extra cost at all. That type of thing happens all the time here.
 
B

bonono

Paul said:
Look at the list.count() example at the start of this thread.
Diagnosing it isn't hard. Curing it isn't hard. It doesn't bloat
Python by an order of magnitude. A suitably factored implementation
might handle lists and strings with the exact same code and not incur
any extra cost at all. That type of thing happens all the time here.
I believe the language creator use the "lack of" as a way to
prevent/discourage that kind of usage. Just like the ternary
operator(still don't know why it is finally accepted). It is not a
problem(not having), it is a feature(to teach you program better), so
what cure are we talking about ?
 
A

Antoon Pardon

No, but if your requirement is to count __eq__ - matching items in a
tuple, maybe your sense of orthogonality ought to abstract out the
sequence aspect in some other way than seeing it as a seeming method
requirement for tuple. A tuple.count method has implications about
attribute access to a special object, tuple, which then you have
to deal with for every new object you introduce, unless you want to
inherit it from object, but that means object becomes a
mega swiss army knife in short order.

I'm open too other possibilties, and I'm interrested in your iterator
methods. It is just that on the one hand people talk about the
advantages of tuples as keys, (no need to copy the keys, since
they are immutable) while on the other hand when tuples lack
some functionality tell me to cast them as lists, completely
eliminating the adavantage tuples have.
So IMO the thing is not to ask for a specific solution like "why
not a count method for tuples?" You'll just get answers to that literal
question, with some elaborations. Instead, if you put it in the form
of what your general requirement really is (I'm guessing ;-) which I
assume is to be able to apply list count method _functionality_ to
anything which quacks like a list, including tuples etc. In short,
anything iterable.

Sure, A base sequence type, from which tuples and lists would inherit
that would provide for this functionality would be good too. Of
course it isn't that difficult to write a general function that works
on any iterable either.
Now the problem is to bring program and data together with some
spelling in python. data.method() is certainly one spelling, but
so is method(data). You gain something either way. The first allows
you to associate the method and data without executing the method, i.e.,
data.method is a bound method object that has the data-method association
built in, and it can be passed around.

There are other ways to get a bound method like object, so I don't
consider that a big advantage.
method(data) does the call right
away and uses a diferent name space search path to find method, and is
not necessarily associated with type(data). To ask for common methods
for all objects that exhibit some similar aspect is to entangle their
types in some way or to duplicate stuff. Sometimes it's fine to
derive from a common base etc., but

why not a built-in count function that does something like (untested)

def count(obj, match_item, eq=operator.eq):
return sum(1 for item in iter(obj) if eq(item, match_item))

Sure. The problem here is a bit about python only providing a partial
solution. If python didn't provide any count methods I think nobody
would have complained. If you needed this, you could easily provide
it your self.

But now python does provide it, but not for all classes it seems
applyable to, so people question why.
which would give a little flexibility about eq comparison as well as
wide applicability to any sequence? index too (untested)

def index(obj, match_item, eq=operator.eq):
try: return (i for i, item in enumerate(obj) if eq(item, match_item)).next()
except StopIteration: raise ValueError('index(seq, item): item not in seq')

why doesn't list have a find like str? ;-)

def find(obj, match_item, eq=operator.eq):
try: return (i for i, item in enumerate(obj) if eq(item, match_item)).next()
except StopIteration: return -1

One could create an alternate spelling for obj.count(thing) using the count function above.
You can spell it now as

count.__get__(obj, type(obj))(thing)

if you want to duplicate the effect of having the count function retrieved from type(obj)
as if it were a method defined there. Or you can spell it

count(obj)

which doesn't seem too bad ;-)
But now the problem is cluttering the __builtins__ space. So maybe it would be
better to write
from sequence_goodies import count
...
count(obj)

Sure, thanks for the suggestion, I think I'll write me a sequence module
with these and similar function. It seems just a bit stupid, because
once I wrote all of these, a number of list methods seem just a waste
that is to be carried along.
Do you really want a count method for tuple? Or is that maybe not as clean is
it seemed? All the issues aren't usually immediatly apparent, so IMO the more
we focus on abstract functionality desired, the more likely we will get
helpful solution ideas for a menu of choices, and avoid prematurely discussing
whether we should have pumpkin pie with or without whipped cream, when finally
we might all like strawberries and cream better, if someone had thought of it.

Well my preferred solution, would have been if sequence had been a mixin
class, that would provide a number of methods for subclasses that
provide the right protocol and then tuple and list being such a
subclass. I think that would have been more pythonic than your suggested
solution, but I think your suggestion is a valuable alternative.
 
M

Mike Meyer

Paul Rubin said:
Yes. The idea of using a program that someone else wrote, is that
they do the work so I don't have to. If their doing less work means
that I have to do more, the program isn't as good as it might be.

No, it's not as good *for your purpose* as it might be. But they
didn't write it for your purpose, they wrote it for theirs. The latter
is really the only standard of judgement.
A program like Python intended for wide distribution and use by large
numbers of people whose needs aren't known in advance, should do as
much to help its users as development resources allow.

True. You seem to disagree about how they choose to allocate the
resources. The fix for that is well-known.
Are you familiar with R. Gabriel's piece "Worse is better"? That's
not what I see "practicality beats purity" as being intended to mean.

Why not? That seems to summarise a couple of the points in the more
successful design philosophy, most notably:

The design most not be overly inconsistent.
The design must cover as many important situations as is practical.

If these don't reflet what you think "Practicality beats purity"
means, then what do you think it means?

Actually, I've been thinking about that bit recently, and noting that
a number of things from "import this" seem to espouse the more
successful approach from that section:

Simple is better than complex.
Complex is better than complicated.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Look at the list.count() example at the start of this thread.
Diagnosing it isn't hard. Curing it isn't hard. It doesn't bloat
Python by an order of magnitude.

Did somebody actually use "Practicality beats purity" as an excuse for
not making list.count and string.count have the same arguments? If so,
I missed it. I certainly don't agree with that - count ought to work
right in this case.
A suitably factored implementation might handle lists and strings
with the exact same code and not incur any extra cost at all. That
type of thing happens all the time here.

If it happens all the time, you shouldn't have any trouble nameing a
number of things that a majority of users think are misfeatures that
aren't being fixed. Could you do that?

<mike
 
C

Christoph Zwerschke

I believe the language creator use the "lack of" as a way to
prevent/discourage that kind of usage. Just like the ternary
operator(still don't know why it is finally accepted). It is not a
problem(not having), it is a feature(to teach you program better), so
what cure are we talking about ?

Sorry, but I still do not get it. Why is it a feature if I cannot count
or find items in tuples? Why is it bad program style if I do this? So
far I haven't got any reasonable explanation and I think there is no.

-- Christoph
 
B

bonono

Christoph said:
Sorry, but I still do not get it. Why is it a feature if I cannot count
or find items in tuples? Why is it bad program style if I do this? So
far I haven't got any reasonable explanation and I think there is no.
I have no idea, I can understand their view, not necessarily agree. And
reasonable explanation is not something I usually find on this group,
for issues like this.
 
C

Chris Mellon

Sorry, but I still do not get it. Why is it a feature if I cannot count
or find items in tuples? Why is it bad program style if I do this? So
far I haven't got any reasonable explanation and I think there is no.

-- Christoph


I'd have to say this:

First, remember that while your idea is obvious and practical and
straightforward to you, everybodys crummy idea is like that to them.
And while I'm not saying your idea is crummy, bear in mind that not
everyone is sharing your viewpoint.

If you want to make changes to the language, you need to be prepared
to convince other people that your idea really is a good one.
Therefore:

Be prepared to present a use case. If your idea really is
straightforward, simple, and obvious this should be fairly easy. It is
possible that your idea is so simple and obvious that everyone will
agree with it, do not expect this to be the case no matter how simple
and obvious it seems to you.

Be prepared to defend your use case. If people show reasons why your
use case is invalid, be prepared to consider that you may be wrong. If
you're still sure that you aren't, present a different use case -
don't expect other people to imagine one for you.

If you *really* want a language feature changed, be prepared to
present a patch for it. If you aren't willing or able to implement it
yourself, you must convince someone else that not only is your change
a good idea, but that it's a good enough idea that they should work on
it, which is always more of an uphill battle.

There may be different subjective or conceptual reasonings at work -
like you wanting to treat tuples as first class sequences while others
(like Guido) want to treat them otherwise. There's no right answer in
a subjective argument, so be prepared to present practical support,
and, unless you're the BDFL, be prepared to be ignored. If it bothers
you enough, you know what your options are.
 
C

Chris Mellon

On 11/30/05 said:
(e-mail address removed) wrote
Paul Rubin wrote
Look at the list.count() example at the start of this thread
Diagnosing it isn't hard. Curing it isn't hard. It doesn't bloa
Python by an order of magnitude. A suitably factored implementatio
might handle lists and strings with the exact same code and no incu
any extra cost at all. That type of thing happens all the tim here

I believe the language creator use the "lack of" as a way t
prevent/discourage that kind of usage. Just like the ternar
operator(still don't know why it is finally accepted). It is not
problem(not having), it is a feature(to teach you program better) s
what cure are we talking about

Sorry, but I still do not get it. Why is it a feature if I canno coun
or find items in tuples? Why is it bad program style if I do this S
far I haven't got any reasonable explanation and I think there i no

-- Christop

I'd have to say this

First, remember that while your idea is obvious and practical an
straightforward to you, everybodys crummy idea is like that to them
And while I'm not saying your idea is crummy, bear in mind that no
everyone is sharing your viewpoint

If you want to make changes to the language, you need to be prepare
to convince other people that your idea really is a good one
Therefore

Be prepared to present a use case. If your idea really i
straightforward, simple, and obvious this should be fairly easy. It i
possible that your idea is so simple and obvious that everyone wil
agree with it, do not expect this to be the case no matter how simpl
and obvious it seems to you

Be prepared to defend your use case. If people show reasons why you
use case is invalid, be prepared to consider that you may be wrong. I
you're still sure that you aren't, present a different use case
don't expect other people to imagine one for you

If you *really* want a language feature changed, be prepared t
present a patch for it. If you aren't willing or able to implement i
yourself, you must convince someone else that not only is your chang
a good idea, but that it's a good enough idea that they should work o
it, which is always more of an uphill battle

There may be different subjective or conceptual reasonings at work
like you wanting to treat tuples as first class sequences while other
(like Guido) want to treat them otherwise. There's no right answer i
a subjective argument, so be prepared to present practical support
and, unless you're the BDFL, be prepared to be ignored. If it bother
you enough, you know what your options are
 
D

Donn Cave

Quoth (e-mail address removed):
| Christoph Zwerschke wrote:
....
|> Sorry, but I still do not get it. Why is it a feature if I cannot count
|> or find items in tuples? Why is it bad program style if I do this? So
|> far I haven't got any reasonable explanation and I think there is no.
|
| I have no idea, I can understand their view, not necessarily agree. And
| reasonable explanation is not something I usually find on this group,
| for issues like this.

It's hard to tell from this how well you do understand it, and of
course it's hard to believe another explanation is going to make
any difference to those who are basically committed to the opposing
point of view. But what the hell.

Tuples and lists really are intended to serve two fundamentally different
purposes. We might guess that just from the fact that both are included
in Python, in fact we hear it from Guido van Rossum, and one might add
that other languages also make this distinction (more clearly than Python.)

As I'm sure everyone still reading has already heard, the natural usage
of a tuple is as a heterogenous sequence. I would like to explain this
using the concept of an "application type", by which I mean the set of
values that would be valid when applied to a particular context. For
example, os.spawnv() takes as one of its arguments a list of command
arguments, time.mktime() takes a tuple of time values. A homogeneous
sequence is one where a and a[x:y] (where x:y is not 0:-1) have
the same application type. A list of command arguments is clearly
homogeneous in this sense - any sequence of strings is a valid input,
so any slice of this sequence must also be valid. (Valid in the type
sense, obviously the value and thus the result must change.) A tuple
of time values, though, must have exactly 9 elements, so it's heterogeneous
in this sense, even though all the values are integer.

One doesn't count elements in this kind of a tuple, because it's presumed
to have a natural predefined number of elements. One doesn't search for
values in this kind of a tuple, because the occurrence of a value has
meaning only in conjunction with its location, e.g., t[4] is how many
minutes past the hour, but t[5] is how many seconds, etc.

I have to confess that this wasn't obvious to me, either, at first, and
in fact probably about half of my extant code is burdened with the idea
that a tuple is a smart way to economize on the overhead of a list.
Somewhere along the line, I guess about 5 years ago? maybe from reading
about it here, I saw the light on this, and since then my code has gotten
easier to read and more robust. Lists really are better for all the
kinds of things that lists are for -- just for example, [1] reads a lot
better than (1,) -- and the savings on overhead is not worth the cost to
exploit it. My tendency to seize on this foolish optimization is however
pretty natural, as is the human tendency to try to make two similar things
interchangeable. So we're happy to see that tuple does not have the
features it doesn't need, because it helps in a small way to make Python
code better. If only by giving us a chance to have this little chat once
in a while.

Donn Cave, (e-mail address removed)
 
B

Ben Finney

Donn Cave said:
Tuples and lists really are intended to serve two fundamentally
different purposes.
[...]
As I'm sure everyone still reading has already heard, the natural
usage of a tuple is as a heterogenous sequence. [...] A list of
command arguments is clearly homogeneous in this sense - any
sequence of strings is a valid input, so any slice of this sequence
must also be valid. (Valid in the type sense, obviously the value
and thus the result must change.) A tuple of time values, though,
must have exactly 9 elements, so it's heterogeneous in this sense,
even though all the values are integer.

I have to confess that this wasn't obvious to me, either, at first,
and in fact probably about half of my extant code is burdened with
the idea that a tuple is a smart way to economize on the overhead of
a list. Somewhere along the line, I guess about 5 years ago? maybe
from reading about it here, I saw the light on this, and since then
my code has gotten easier to read and more robust.

Strangely, I learned this as I was learning the language, and
understood it after reading the explanation a couple of times (I can't
remember where I was reading it, but it must have been a decent
guide).

However, in the intervening time I'd forgotten this fundamental
difference between the *purpose* of list and tuple.

Thanks very much for this reminder. You've probably stopped me from
writing a bunch of misguided code and realising 5 years too late :)
 
M

Mike Meyer

Donn Cave said:
Tuples and lists really are intended to serve two fundamentally different
purposes. We might guess that just from the fact that both are included
in Python, in fact we hear it from Guido van Rossum, and one might add
that other languages also make this distinction (more clearly than Python.)

As I'm sure everyone still reading has already heard, the natural usage
of a tuple is as a heterogenous sequence. I would like to explain this
using the concept of an "application type", by which I mean the set of
values that would be valid when applied to a particular context. For
example, os.spawnv() takes as one of its arguments a list of command
arguments, time.mktime() takes a tuple of time values. A homogeneous
sequence is one where a and a[x:y] (where x:y is not 0:-1) have
the same application type. A list of command arguments is clearly
homogeneous in this sense - any sequence of strings is a valid input,
so any slice of this sequence must also be valid. (Valid in the type
sense, obviously the value and thus the result must change.) A tuple
of time values, though, must have exactly 9 elements, so it's heterogeneous
in this sense, even though all the values are integer.

One doesn't count elements in this kind of a tuple, because it's presumed
to have a natural predefined number of elements. One doesn't search for
values in this kind of a tuple, because the occurrence of a value has
meaning only in conjunction with its location, e.g., t[4] is how many
minutes past the hour, but t[5] is how many seconds, etc.

I get all that, I really do. I would phrase it as "a tuple is a set of
attributes that happen to be named by integers." count doesn't make
sense on the attributes of an object - so it doesn't make sense on a
tuple. index doesn't make sense on the attributes of an object - so it
doesn't make sense on a tuple. A loop over the attributes of an object
doesn't make sense - so it doesn't make sense on a tuple.

So why the $*@& (please excuse my Perl) does "for x in 1, 2, 3" work?

Seriously. Why doesn't this have to be phrased as "for x in list((1,
2, 3))", just like you have to write list((1, 2, 3)).count(1), etc.?

<mike
 
B

bonono

Mike said:
I get all that, I really do. I would phrase it as "a tuple is a set of
attributes that happen to be named by integers." count doesn't make
sense on the attributes of an object - so it doesn't make sense on a
tuple. index doesn't make sense on the attributes of an object - so it
doesn't make sense on a tuple. A loop over the attributes of an object
doesn't make sense - so it doesn't make sense on a tuple.

So why the $*@& (please excuse my Perl) does "for x in 1, 2, 3" work?

Seriously. Why doesn't this have to be phrased as "for x in list((1,
2, 3))", just like you have to write list((1, 2, 3)).count(1), etc.?
I don't know what you use tuple for, but I do need to loop over
attributes of an object(be it tuple or dict or even set), though no
need for count(), index(), not even on list, so far.

I think why people may ask for .count() and .index() for tuple is that
if I am writing a generic function that receive such a thing, I don't
need to do a type check or try/except block, should the caller tries to
be smart and use tuple instead of list(say for optimization reason).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,042
Latest member
icassiem

Latest Threads

Top