Attack a sacred Python Cow

T

Terry Reedy

Carl said:
That's not what I was asking for. I was asking for a use case for "if
x" that can't be replaced by a simple explicit test. Your example
didn't satisfy that.

But I believe my example of an iterator with __bool__ but not with
__len__ does.
 
M

Matthew Fitzgibbons

Carl said:
I mean in general. I wouldn't spell it like that. I would prefer if
empty(x), with an __empty__ method. (And support __nonzero__ aka
__bool__ dropped completely.)


Carl Banks

__nonzero__ is not only meaningful for sequence types.

-Matt
 
M

Matthew Fitzgibbons

Russ said:
Oh, Lordy. I understand perfectly well how boolean tests, __len__, and
__nonzero__ work in Python. It's very basic stuff. You can quit
patronizing me (and Carl too, I'm sure).

The point that you seem to be missing, or refuse to acknowledge for
some reason, is that "if x" can be mistakenly applied to any object
when the programmer thinks that x is a list -- and the programmer will
receive no feedback on the error.

I have made errors like that, and I could have saved some time had I
used an "empty" method that only applies to a list or other sequence.

Is that an important issue? I don't know. I'm not claiming it is. But
you cannot just sweep it away as nothing.

See, I can agree with this. If you're expecting a list (and only a list)
then your point makes sense. 'if x' can get you into trouble if you
_don't_ want its polymorphism.

Although, if my function is expecting a list, my preference is to do:

if not isinstance(x, list):
raise SomeMeaningfulException()
# do stuff with the list

I put my type checking at the top of the function, so readers can
reference it easily.

However, Carl's point is that 'if x' is never preferable to the more
verbose and slower "simple test". I do not agree with this.

-Matt
 
M

Matthew Fitzgibbons

Carl said:
I think I see what you're saying, and yeah I guess that could really
take advantage of polymorphism between very different types.


I wasn't suggesting you change it: I was trying to ascertain whether
it would have suffered much if you had written it with explicit tests
in the first place, or if Python didn't even have magical booleans.

Yes it would have suffered. I chose the implementation I did because it
made the most sense to me and was the most flexible (a key requirement).
Instead of cobbling together my own way, I used the way that Python gave me.

Python doesn't have magic booleans. They are instead a very well-defined
language mechanism that isn't perfect for every circumstance, but is
pretty good for the most part. I wanted to do meaningful boolean tests
on various objects, so I used the mechanism that my language gave me.
If you don't mind me asking: what do you do actually DO with a zero or
empty list?

Depends on exactly what the next stage is. Typically, zeros and empty
lists are not meaningful for the next stage, so they get dropped then if
they make it through. I don't want to restrict what gets passed through,
though, because I could end up with several meaningful data types,
making a simple test again impossible. So I pass everything through and
let the next stage decide.
Ah, so it's just happens to work. Still, just happening to work
works. (shrug)

Nonono. The point you seem to be missing is that 'if x' is very well
defined. There is nothing magic or arbitrary about what it does. It
works here and elsewhere because Python (a) chooses good default
behavior (its treatment of lists and ints, etc) and (b) gives you a way,
__nonzero__, to change the behavior to suit your needs.
I wouldn't bother at this point. I was looking to see if someone
could come up with something to disprove my belief on the polymorphic
uselessness of "if x" relative to explicit tests, and if (as I
anticipated) they did not, I could claim that "if x" is really just a
glorified keystroke saver. But I now realize that the failure of this
bunch doesn't prove anything. I don't think most people even realize
why answering the question I asked would demonstrate the usefulness of
"if x".

Of course you don't _need_ to have 'if x'; after all, <sarcasm>REAL
programmers code in machine language</sarcasm>. The whole point of a
high-level language is to make life easier. Python is very dynamic and
allows duck typing so that you can use these tools to do clever things
that would otherwise be very difficult. It even gives you a handy
polymorphic mechanism to do boolean tests, which my example illustrates.

You asked for a use case for a polymorphic 'if x' that can't be easily
replaced by a simple test. I gave one. Then you asked for a code sample,
but now have dismissed my sample as not compelling without having seen
it. But here it is anyway (attached). It's pretty rough since I just
threw it together. I'm sure there are mistakes. I also dropped the DAG,
where all the queueing and decision making is handled in the actual
program. The filters and data are arbitrary but should illustrate the
setup. You care about line 66. Again, the same thing could be
accomplished in various ways; but keep in mind that data could be
_anything_, so you can't easily rewrite line 66.
Your example isn't exactly the smoking gun I was looking for, but I
guess we'll have to admit that at least one usage will suffer for not
having it.


Carl Banks

So you hypothesized that you can easily rewrite any 'if x' as a simple,
explicit test. I produced an example that shows this cannot be done;
therefore your hypothesis is not correct.

For most cases, you can come up with a simple test, even if it's not the
best way to implement you problem. But other times, the poylmorphic,
duck typing behavior of 'if x' allows you to make your problem much
easier, in a way a simple test can't. To deny this fact is to deny to
power of dynamic languages in general.

-Matt
 
M

Matthew Woodcraft

Terry Reedy said:
Carl Banks wrote:
But I believe my example of an iterator with __bool__ but not with
__len__ does.

On the other hand, iterators provide a clear example of problems with "if x":
__nonzero__ for iterators (in general) returns True even if they are 'empty'.

For example, this function (which attempts to avoid making an expensive
call when not necessary) is buggy, but easy to write if you've been
taught that "if x" will work with any kind of object.

def frob(widgets, power):
if widgets:
frobber = Frobber(power) # expensive call
for widget in widgets:
frobber.frob(widget)

-M-
 
R

Russ P.

You suggested a syntax for testing non-emptiness (`x is not empty`)
which indicated a profound misunderstanding of what the `is` operator does.

You then acknowledged that there might be a problem because of the
implication if the `is` operator and weren't sure whether it would work
or not:

Oh, my. I wrote something like, "It would sure be nice to be able to
write

if x is not empty:

because it reads like natural language. Immediately after I posted it,
I thought, "oh, I'll bet some idiot takes that as a serious proposal."
Sure enough, some idiot did just that almost immediately. And he is
still patronizing me for it.

Hey, dude, if you think I ever had any doubt about what "is" means in
Python, you are simply wrong. Completely wrong. Can you get that
through your thick skull?

One of the problems with this site is that you have pedants who like
to show off their knowledge of the Python language. I suspect that
many of these people know little more than the rules of programming in
Python. They are like someone who thinks he is a writer because he
knows how to use Microsoft Word, or someone who thinks he is a chess
expert because he knows the rules for moving the pieces.
 
C

Carl Banks

So your argument is purely about style, then. You just wish it were
written differently.

No, you misunderstand and/or misstate my position again. I realize I
wasn't as clear as I could have been. First of all it's not my
"argument": this is a tangent.

There would be a built-in empty, which invokes __empty__, in the same
way len invokes __len__. It would only be defined for container
types. (Iterators could choose whether to define it and it would mean
that the iterator is guaranteed stop on the next iteration. The
iterator is free to read and store the item. If the iterator doesn't
know whether it will stop, it must not define __empty__ or raise an
exception in it.) It would become the One Obvious Way to test for
emptiness. __nonzero__ would disappear and not be replaced with
anything, and objects would not have implicit boolean conversion.


Carl Banks
 
C

Carl Banks

Even for those that did realize, and in fact hoped that that is what you
were attempting to accomplish,

I was not attempting to accomplish what you think I was.

I was looking for it, but I didn't want to see it. I didn't expect to
see it. I wanted to show that "if x" doesn't have the polymorphic
advantage people mindlessly claim it does by posing the challenge and
having people fail to meet it, and for the most part the examples that
met the challenge were for minor usages. Ok, someone wrote a filter
that truly benefits from polymorphism of "if x" against very different
types, but really, these use cases aren't all that common.

It's not like it's an everyday thing for you to write "if x" instead
of "if x!=0", and that it actually saves you from having to rewrite
the condition because later you decided to use a list.

So I stand by the point I was trying to make: for your average day-to-
day programming, the main benefit of "if x" is to save keystrokes. It
doesn't help your code become more polymophic in practice. A little
more polymorphic, yes. A lot, no.
it was still quite frustrating to see you
ignoring all the non-code, yet perfectly valid examples of why "if x"
was not only valid, but the most pythonic[1] way to get the task done.

Pfft. The usage of "if x" might be Pythonic, but I think the best way
is the way Java does it.
I think it would have been a better discussion if you had responded with
reasons why, and not just parroted the "show me the code!" line over and
over and over and ... It seemed as if you thought you were the
professor, impatiently trying to teach a class full of idiots by playing
the devil's advocate.

I wasn't playing Devil's advocate, I was playing the Devil. That's
why I did that. Sorry if it irritated people but I wasn't about to
those things distract me.
I was sure hoping someone would get the actual
code example and post it, partly because I enjoy learning, but mostly
because it would (hopefully) shut you up and move the conversation
along. In fact, somebody did post some code about a custom matrix
class, where __len__ was useless, and still you kept on with... pah.

I admit it! I downplay even successful examples because I just don't
like implicit booleans. What can I say, I'm an optimist.

I didn't see any custom matrix class, BTW. The only code I saw was
Steven D'Aprano filter which he still apparently expects me to take
his word for it that the alternative I proposed won't work, and Terry
Reedy's empty-enabled iterator. Oh, also Heiko Wundram's integer set.
It's late, so before I say something stupid I'll finish this. My last
thought on the matter -- up until this thread I had looked forward to
your posts, Carl. I think you did more damage than good to yourself
with this stunt.

Sorry, but I must go on a crusade every once in awhile, whatever
damage it may cause my esteem. It's in my nature.


Carl Banks
 
C

castironpi

I mean in general.  I wouldn't spell it like that.  I would prefer if
empty(x), with an __empty__ method.  (And support __nonzero__ aka
__bool__ dropped completely.)

Carl Banks

An __empty__ method could return True for my social life, ha ha. Does
__nonzero__ just mean __nonempty__?
 
R

Russ P.

Yes, all people are idiots for reading what you wrote, reading your
later realization that it was wrong, and taking both at face value.
I'll be sure never to make that mistake again!


No, I'm not patronizing you for your initial misstatement. I'm mocking
you for your pathetic and transparent attempt to backpedal away from it.
Just give it up, already.

--
Erik Max Francis && (e-mail address removed) &&http://www.alcyone.com/max/
San Jose, CA, USA && 37 18 N 121 57 W && AIM, Y!M erikmaxfrancis
Drifting from woman-who-tries misconstrued / Shifting to woman-wise
-- Lamya

The reason I wrote that "it would be nice to be able to write"

if x is not empty:

is that it reads naturally. It was not an actual proposal, and the
fact that you took it as such was *your* mistake. I can understand
your misunderstanding one time, but you have now repeated it three
times, despite my (unnecessary) explanations. One more time, and you
graduate from idiot to moron.

Having said that, the syntax I wrote *could* conceivably work IF all
empty lists pointed to one empty list, just as all values set to None
actually point to the same None. That is possible, but probably not a
good idea.

Now read carefully: I DID NOT CLAIM THAT THIS IS THE WAY TO DO IT! Let
me repeat that for you: I DID NOT CLAIM THAT THIS IS THE WAY TO DO IT!
Did you get that, idiot?
 
S

Steven D'Aprano

If you're expecting a list (and only a list)
then your point makes sense. 'if x' can get you into trouble if you
_don't_ want its polymorphism.

"if x" is hardly unique in that way. If you're expecting a list, and only
a list, "len(x) != 0" will get you in trouble if somebody passes a string
or a dictionary. I don't see any reason why we should single out "if x"
as dangerous in the face of invalid types. With the exception of the "is"
and "is not" operators, nothing in Python is guaranteed to work with any
imaginable object. Even print can fail, if the object's __str__ method
raises an exception.

Although, if my function is expecting a list, my preference is to do:

if not isinstance(x, list):
raise SomeMeaningfulException()
# do stuff with the list

I put my type checking at the top of the function, so readers can
reference it easily.

And thus you break duck-typing and upset anybody who wants to pass a
sequence that doesn't inherit directly from list.

There are other (and arguably better, although more labour-intensive)
techniques for defensive programming that don't break duck-typing. You
can google for Look Before You Leap and Easier To Ask Forgiveness Than
Permission for more information. Alex Martelli has a fine recipe in the
Python Cookbook -- search for the recipe "Checking if an object has the
necessary attributes".

But in a nutshell, here's a toy example:

def spam(seq):
try:
seq.append
seq.extend
seq[0] = seq[0]
except Exception:
raise TypeError("argument isn't sufficiently sequence-like")
# No exceptions expected from here on
seq.append(seq[0])
seq.extend([1,2,3])
seq[0] = "spam"
 
S

Steven D'Aprano

On the other hand, iterators provide a clear example of problems with
"if x": __nonzero__ for iterators (in general) returns True even if they
are 'empty'.

How do you propose telling whether an iterator is empty?

That's a generic problem with any sort of lazy function. You don't know
if it has finished unless you try grabbing data from it.


For example, this function (which attempts to avoid making an expensive
call when not necessary) is buggy, but easy to write if you've been
taught that "if x" will work with any kind of object.

def frob(widgets, power):
if widgets:
frobber = Frobber(power) # expensive call
for widget in widgets:
frobber.frob(widget)


AFAIK there's no great solution to this problem. It's inherent in the way
lazy functions work. Certainly you can't replace the call to "if widgets"
with "if len(widgets)", because iterators don't have a length.

However, there is a good (but not great) solution:

def frob(widgets, power):
widgets = iter(widgets) # in case widgets is a sequence
try:
first = widgets.next()
except StopIteration:
# empty iterator, nothing to do
return None
frobber = Frobber(power) # expensive call
frobber.frob(widget)
for widget in widgets:
frobber.frob(widget)
 
R

Russ P.

So people who can read words but not minds are idiots. Go get 'em, tiger!

I don't know if you can read minds, but you seem to have a lot of
trouble reading words.

Can you read "it would be nice to be able to write ..."? Can you
understand what it means? Can you understand that it does *not* mean,
"one *should* be able to write ..."?

The really significant question here is why I waste my valuable time
with pedants like you.
 
S

Steven D'Aprano

And thus you break duck-typing and upset anybody who wants to pass a
sequence that doesn't inherit directly from list.

Correction: delete "directly" from the above.
 
R

Russ P.

I don't know if you can read minds, but you seem to have a lot of
trouble reading words.

Can you read "it would be nice to be able to write ..."? Can you
understand what it means? Can you understand that it does *not* mean,
"one *should* be able to write ..."?

The really significant question here is why I waste my valuable time
with pedants like you.

Folks, I'm sorry for being so harsh here. But this guy keeps insisting
that I dispayed a "fundamental lack of understanding" of the correct
usage of "is" in Python. If that were true, I would have gladly
admitted it and dropped the matter. But it is completely false. The
simple fact is that I fully understood how "is" works in Python from
the first time I read about it -- as I'm sure most others here did
too. It just gets my goat that someone would latch onto some whimsical
suggestion I wrote to try to prove otherwise.

He did not need to play that silly little game, and he could have
easily avoided my insults had he not played it.
 
E

Ethan Furman

Carl said:
I was not attempting to accomplish what you think I was.

I was looking for it, but I didn't want to see it. I didn't expect to
see it. I wanted to show that "if x" doesn't have the polymorphic
advantage people mindlessly claim it does by posing the challenge and
having people fail to meet it, and for the most part the examples that
met the challenge were for minor usages. Ok, someone wrote a filter
that truly benefits from polymorphism of "if x" against very different
types, but really, these use cases aren't all that common.

It's not like it's an everyday thing for you to write "if x" instead
of "if x!=0", and that it actually saves you from having to rewrite
the condition because later you decided to use a list.

Actually, I use this construction a lot. But everybody has their own
style, and I'm certainly not going to tell you yours is wrong. One of
the fellows that works for me *loves* the (result if false, result if
true)[condition] style of immediate if's -- it's one of the first things
he learned about when studying Python, and he grins every time he talks
about it; *I* know it's not the best way to do it, and that it has it's
own set of gotchas -- so I made sure he was also aware of them, and uses
them where and when they won't blow up in our faces.
So I stand by the point I was trying to make: for your average day-to-
day programming, the main benefit of "if x" is to save keystrokes. It
doesn't help your code become more polymophic in practice. A little
more polymorphic, yes. A lot, no.
[snippitysnipsnip]

Carl Banks

Hmmm... well, I see your point. Unfortunately, even though it feels
incorrect to me, I do not (yet) have the breadth and depth of Python
experience to come up with an example that would display such exquisite
polymorphism. It also seems to me that such an example would be
non-trivial in nature. Perhaps starting a new thread with this
challenge, and adequate time (couple weeks at least, I would think)
would net you the smoking gun you were after.

At any rate, from my point of view, I like it. I like the visual
clarity and simplistic nature of "if x" -- it tells me "if x is
something", and I trust myself enough to know what I can do with the
something that is x. I also expect anyone else passing me a something
to know it has the appropriate interface to work with my code.

~Ethan~
 
E

Ethan Furman

Russ P. wrote:

[snippers]
The reason I wrote that "it would be nice to be able to write"

if x is not empty:

is that it reads naturally.

[and more snippers]

Reads naturally? For whom? "Readability counts" does not mean "make it
sound like english as much as possible". There are good reasons for not
having computer languages written in human language. If that's really
what you want, go join Dave Parker and Flaming Thunder. Or write that
preprocessor that someone keeps yammering about and have it take code
the way you want to write it and convert it to actual Python. Would be
an interesting experiment, anyway.

~Ethan~
 
R

Russ P.

You're sure going on about a distinction without a difference for a guy
who childishly likes to call other people names. A reasonable person
would have long ago moved on instead of blaming others for not
immediately intuiting your thoughts, rather than straightforwardly
reading your words. Which, by the way, includes at least three people
other than myself.

But I'll bet the mindless namecalling is really working out for you.
Go, team, go!

You earned the "childish name calling" by acting like a child -- with
your petty little game of trying to show that I don't understand a
basic concept in Python. As I said, your initial misunderstanding,
while silly, was at least forgivable. But your insistence on repeating
it time after time is not. It is truly pathetic.
 

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

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top