Eval of expr with 'or' and 'and' within

G

Grant Edwards

With a few random oddities:

True

I somehow expected NaN to be false. Maybe that's just my expectations
that are wrong, though.

If you work with floating point long enough you realize that most of
your expectations are wrong. Sometimes. Eventually.
 
G

Grant Edwards

On 14/6/2013 7:47 ????, Benjamin Kaplan wrote:
In an "and" clause,


This is exactly what i dont understand and thats why i keep asking and
people call me an idiot. I just dont understand why it behaves like that.

Why return first or last value?

There are cases where it's useful not only to know wether an
expression was True or False, but _why_ it was true or false.
because that will evaluate to the correct Boolean value ????

Yes. All values in Pyton have a "truthness" and you can be guaranteed
that

if A or B or C:

will behave exactly the same way whether the "or" operator returns
True or it returns one of it's operands.
 
N

Nobody

2. Returning one the objects that result from the evaluation of the
operands instead of returning True or False.

This is what seems to be confusing him. This is much less common
than short-circuit evaluation.

FWIW, Lisp also does this. But Lisp is slightly simpler as the only false
value is "nil", while everything else is true (including integer zero).

Although Python's any() and all() (which are closer to Lisp's "and" and
"or" insofar as they all work with any number of values, including zero)
always return True or False rather than the final value.
 
N

Nobody

Unlike Javascript though, Python's idea of truthy and falsey is actually
quite consistent:

Beyond that, if a user-defined type implements a __nonzero__() method then
it determines whether an instance is true or false. If it implements a
__len__() method, then an instance is true if it has a non-zero length.
 
N

Nobody

With a few random oddities:

True

I somehow expected NaN to be false. Maybe that's just my expectations
that are wrong, though.

In general, you should expect the behaviour of NaN to be the opposite of
what you expect.
 
C

Cameron Simpson

| I started another thread because the last one was !@#$'ed up by
| irrelevant replies and was difficult to jeep track.
|
| >>> name="abcd"
| >>> month="efgh"
| >>> year="ijkl"
|
| >>> print(name or month or year)
| abcd
|
| Can understand that, it takes the first string out of the 3 strings
| that has a truthy value.
|
| >>> print("k" in (name and month and year))
| True
|
| No clue. since the expression in parenthesis returns 'abcd' how can
| 'k' contained within 'abcd' ?

Did you print the result of "name and month and year"? It is the
_last_ value (if true at all). You used "or" in the first example
and "and" in the second.

| >>> print(name and month and year)
| ijkl
|
| Seems here is returning the last string out of 3 strings, but have
| no clue why Python doing this.

To evaluate an "and" it must test all of them to be true, and it
keeps the last value tested. (Or False, of course, if they are not
all true, in which case Python stops testing at the first False).

But for what you are doing, "and" and "or" are not good operations.

Something like:

"k" in (name+month+year)

or

"k" in name or "k" in month or "k" in year

is a more direct and accurate way to write what I imagine you're trying to do.

Cheers,
 
M

MRAB

Beyond that, if a user-defined type implements a __nonzero__() method then
it determines whether an instance is true or false. If it implements a
__len__() method, then an instance is true if it has a non-zero length.
It's __nonzero__ in Python 2, __bool__ in Python 3.
 
S

Steven D'Aprano

In general, you should expect the behaviour of NaN to be the opposite of
what you expect.

.... even taking that into account! *wink*


Everyone is aware that there is more than one NAN, right? If my
calculations are correct, there are 9007199254740992 distinct float NANs
in Python (although there is no direct way of distinguishing them). Half
have the sign bit set, half do not; half are quiet NANs and half are
signalling NANs. It would be too easy if "sign bit set" meant signalling,
so in fact there are four equal-numbered groups of NANs, 2251799813685248
each of:

+quiet
+signalling
-quiet
-signalling

where the - sign should be interpreted as "sign bit is set" rather than
"negative", and + sign as "sign bit not set".

They differ according to their bit-pattern, or payload. Some systems
actually give standard meanings to different bit patterns, e.g. in the
old SANE (Standard Apple Numerics Environment) system, different NANs
were produced according to different kinds of errors, e.g:

Payload Description
======= ==========================================
1 Invalid sqrt
2 Invalid addition, e.g. +INF + -INF
3 Invalid division, e.g. 0/0
17 Convert invalid string
21 Attempt to create NAN with 0 as payload

etc.

(Assigning meaning to the payload is optional, according to the IEEE 754
standard, if I recall correctly.)
 
C

Cameron Simpson

| On Sat, 15 Jun 2013 00:09:31 +0100, Nobody wrote:
|
| > On Sat, 15 Jun 2013 03:56:28 +1000, Chris Angelico wrote:
| >> With a few random oddities:
| >>>>> bool(float("nan"))
| >> True
| >> I somehow expected NaN to be false. Maybe that's just my expectations
| >> that are wrong, though.
| >
| > In general, you should expect the behaviour of NaN to be the opposite of
| > what you expect.
|
| ... even taking that into account! *wink*
|
| Everyone is aware that there is more than one NAN, right?

I was not. Interesting.

| If my
| calculations are correct, there are 9007199254740992 distinct float NANs
| in Python (although there is no direct way of distinguishing them).

Wouldn't id() do it? At least in terms of telling them apart?
I gather they're not inspectable in Python?

Cheers,
 
C

Chris Angelico

| Everyone is aware that there is more than one NAN, right?

I was not. Interesting.

| If my
| calculations are correct, there are 9007199254740992 distinct float NANs
| in Python (although there is no direct way of distinguishing them).

Wouldn't id() do it? At least in terms of telling them apart?
I gather they're not inspectable in Python?

You could recognize one float object as distinct from another, but
that's true of all floats:
False

All NaNs are different in terms of the == operator, so conceptually
there are an infinite number of unique NaNs. The fact that they're
stored in memory using a certain number of bits means that there must
be a finite number of possible representations, but that's really an
implementation detail. I suppose you could figure out the
representation differences by fiddling with ctypes (in C I'd just use
a union), but that's really all.

ChrisA
 
S

Steven D'Aprano

| ... even taking that into account! *wink* |
| Everyone is aware that there is more than one NAN, right?

I was not. Interesting.

| If my
| calculations are correct, there are 9007199254740992 distinct float
| NANs in Python (although there is no direct way of distinguishing
| them).

Wouldn't id() do it? At least in terms of telling them apart? I gather
they're not inspectable in Python?

I'm not talking about different *objects*. It would be terribly wasteful
for Python to pre-allocate 9-gazillion NAN objects. I'm talking about
distinct values, in the C-double sense.

Python may or may not cache floats in general. In general, it doesn't:

py> x = 2.5
py> y = 2.5
py> x is y
False


but in principle Python might choose to cache some, or all float objects,
like it does with some ints and strings:

# simulated, not real
py> x = 0.0
py> y = 0.0
py> x is y
True

So you can always distinguish two floats, including NANs, *by value* with
== and by *object identity* with id() and `is`. But that's not what I'm
referring to.

The layout of a C double (the numeric value of a float object) is 64 bits:

|s|..e..|......f......|

where s is a single sign bit, e is an 11-bit biased exponent, and f is a
52-bit binary fraction. If e is 2047 (0b11111111111) then the double is a
special value, either an INF or a NAN:

e = 2047, f == 0: double is +INF or -INF, depending on s

e = 2047, f != 0: double is a NAN

With a 52-bit f field, there are 4503599627370496 distinct payloads with
the sign bit set, and another 4503599627370496 with it cleared. Python
gives you no direct way of testing or setting that payload, or for that
matter the sign bit, on a NAN, although you can use the struct module to
cast a float to a 64-bit int and then do bit twiddling. But in principle,
with 51 (why not 52? see below) bits available, you can stuff quite a
fair bit of diagnostic information in a NAN, if you need to.

The high bit of f is reserved for a special purpose. If the high bit is
set (i.e. f >> 51 == 1) the NAN is considered a signalling NAN, which (in
implementations that comply with the IEEE 754 standard) are guaranteed to
halt the calculation immediately. Those with it cleared are quiet NANs,
and are intended to propagate through calculations[1], although that is
configurable[2].




[1] It's not quite true that once a NAN has entered a calculation, it is
guaranteed to be the final result. There are circumstances where NANs can
legitimately disappear from a calculation, leaving an actual number.

[2] Python doesn't allow you to configure float's behaviour but the
Decimal module does.
 
A

alex23

To everyone else... I know that Nikos' posts are draining. Sometimes he
brings me to the brink of despair too. But if you aren't part of the
solution, you are part of the problem: writing short-tempered, insulting
posts after short-tempered, insulting post doesn't teach him, it just
adds to EVERYBODY'S frustration with this never-ending serious of threads..

What about our frustration that this thread has become so overwhelmingly his support group? It's not like there isn't a list where he could post absolute beginner questions:

http://mail.python.org/mailman/listinfo/tutor

Although I'm pretty sure their first response would be "read the docs / play with the interpreter", neither of which he's shown any desire to do.
Please keep the snarky comments offlist.

Tried that. He posts them back here.

Alternatively, I'd ask that if you're so willing to deal with him, that the*two of you* take this show offlist instead? I'm genuinely curious as to whether he'd agree to this: given his propensity for changing his mail headers so regularly, the whole thing still screams performance troll. (I mean, seriously, how many days elapsed between his being burned by Chris Angelo and him offering to give you access to his server? Isn't refusing to budge from a position the defining characteristic of a ferrous cranus?)
 
N

Nick the Gr33k

Tried that. He posts them back here.

Alternatively, I'd ask that if you're so willing to deal with him, that the *two of you* take this show offlist instead? I'm genuinely curious as to whether he'd agree to this: given his propensity for changing his mail headers so regularly, the whole thing still screams performance troll. (I mean, seriously, how many days elapsed between his being burned by Chris Angelo and him offering to give you access to his server? Isn't refusing to budge from a position the defining characteristic of a ferrous cranus?)

I called my self 'Ferrous Cranus'(this is what a guy from a forum
initially called me for being hard-headed :) ) because i'm indeed
hardheaded and if i believe that 1 thing should have worked in some way
i cant change my mind easily that it works in another fashon(only if the
counter-arguments are strong).
Being strong-headed != acting as a troll


About the changing of NNTP hosts. (well Google Groups gave me and you
issues with its constant adding of '\n' between lines. I was given many
complains about that so as Chris suggested i ditched Google Groups and
try to find out how i can use TB instead.

As for the mail, i decided since my questions concern python and my
website to change the gmail address to support@.... which is more relevant.

I have also correct each time my spelling before i post.

Now as for you, you should be thankful for Steven and Cameron answers to
this groups because answering my questions.

1. help me
2. help others, which afraid to ask, in the propensity of being laughed upon
3. help other groups members like Michale Torrie whose admitted that
some of the explanation was useful to him and he didn't knew that
Boolean expressions can return string values instead of True or False.
3. help you, because you are being educated yourself too, because i
sincerely doubt if you knew anything i i have asked.

So, stop complaining and try to be helpful here or just mute my thread
as Chris suggested as a working solution opposed to kill filing.
 
D

Denis McMahon

I called my self 'Ferrous Cranus'(this is what a guy from a forum
initially called me for being hard-headed :) ) because i'm indeed
hardheaded and if i believe that 1 thing should have worked in some way
i cant change my mind easily that it works in another fashon(only if the
counter-arguments are strong).

Then you need to stop trying to write python code, because you refuse to
accept how python works, and python is not going to change for you!
 
N

Nick the Gr33k

Python implements these operators by returning the actual value which
determined the result of the expression rather than simply True or False.

which in turn the actual value being returned is a truthy or a falsey.

That cleared the mystery in my head entirely.
I wouldn't have asked so many follow-up questions in the thread if i
received that kind of a response.

Thank you very much for this response.
If the result is known after evaluating the first argument, the first
argument is returned. If it has to evaluate the second argument, the
second argument is returned (by that point it has already forgotten
the value of the first argument).

So, the less it has to calculate to determine the correct result of an
expression the better.

Thanks again very much.
 
N

Nick the Gr33k

Then you need to stop trying to write python code, because you refuse to
accept how python works, and python is not going to change for you!

Given the right counter-arguments one can't make a stand against
something that is without no doubt True.
 
N

Nick the Gr33k

| I started another thread because the last one was !@#$'ed up by
| irrelevant replies and was difficult to jeep track.
|
| >>> name="abcd"
| >>> month="efgh"
| >>> year="ijkl"
|
| >>> print(name or month or year)
| abcd
|
| Can understand that, it takes the first string out of the 3 strings
| that has a truthy value.
|
| >>> print("k" in (name and month and year))
| True
|
| No clue. since the expression in parenthesis returns 'abcd' how can
| 'k' contained within 'abcd' ?

Did you print the result of "name and month and year"? It is the
_last_ value (if true at all). You used "or" in the first example
and "and" in the second.

okey, lets see it again:

Yes, 'k' isn't contained in the result string 'abcd'
True

Yes they work as expected, i was mistaken, sorry.

| >>> print(name and month and year)
| ijkl
|
| Seems here is returning the last string out of 3 strings, but have
| no clue why Python doing this.

To evaluate an "and" it must test all of them to be true, and it
keeps the last value tested. (Or False, of course, if they are not
all true, in which case Python stops testing at the first False).

Yes, i know it behaves like that, the question is why:

As "Nobody" explained to me, the reason is that Python expressions
results back the argument that determined the evaluation of the Boolean
expression, which in turn can be a truthy or a falsey used in 'or' or
'and' respectively.

Returning a truthy value equals True
returning a falsey value equals False

so it all boils down to the Booleans type of values True or False.

But for what you are doing, "and" and "or" are not good operations.

Something like:

"k" in (name+month+year)

or

"k" in name or "k" in month or "k" in year

Used to wrote it myself like the latter but needed a more compact way of
writing it for clarity so i used the former.

but those 2 gives the same results back

"k" in (name+month+year) == "k" in (name and month and year)
True

so both seem to work as expected.
 
L

Lele Gaifax

Nick the Gr33k said:
Used to wrote it myself like the latter but needed a more compact way
of writing it for clarity so i used the former.

but those 2 gives the same results back

"k" in (name+month+year) == "k" in (name and month and year)
True

so both seem to work as expected.

That happens only by chance: it seems you now understand the evaluation
of "boolean" expressions in Python, so the following should be clear to
you:
False

ciao, lele.
 
N

Nick the Gr33k

That happens only by chance: it seems you now understand the evaluation
of "boolean" expressions in Python, so the following should be clear to
you:

True

ALL strings in the parenthesis are being concatenated to a BIG string,
like ('k' in BIG_string) which returns the Boolean value of True since
'k' is contained within it.

first the expression of the parenthesis evaluation.

The argument being returned from ("there" and "is" and "a" and "k" and
"character" and "somewhere") expresssion, is the one that is responsible
for the determination of the expression's evaluation.
That would be the last argument, string "somewhere" because:

1. All previous strings before the last one were found truthies, so it
was turn of the last one to be evaled too.

2. Since "somewhere" is a truthy of course for being a non-empty string
then ALL arguments of the expression are found TRUE which results for
the expression to stand TRUE.

3. What determined the expression to stand TRUE was the evaluation of
the last argument "somewhere", so the latter was the key factor for that
to happen, hence its being returned back as a result(thats how Python works)

4. so it's like checking if ('k' in "somewhere") which return the
Boolean value of False since the aforementioned char isn't contained in
the aforementioned string.
 

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,797
Messages
2,569,647
Members
45,377
Latest member
Zebacus

Latest Threads

Top