"0 in [True,False]" returns True

M

Mike Meyer

Fredrik Lundh said:
footnote: strictly speaking, minimized attributes have values but no names;
it's up to the parser to determine what attribute you're setting when you
specify the value.
(for example, in <img ismap>, "ismap" is the value, not the attribute name.
it's up to the parser to figure out (from the DTD) that this value can only
be used by the "ismap" attribute, and interpret it as <img ismap=ismap>)

But this isn't necessarilly true: <img alt=ismap> is perfectly legal.
I would say that ismap only has one valid value - "ismap", so the
parser knows that it should interepret a bare "ismap" as ismap=ismap,
which gets you the same behavior in the end.

<mike
 
F

Fredrik Lundh

Mike said:
But this isn't necessarilly true: <img alt=ismap> is perfectly legal.
I would say that ismap only has one valid value - "ismap", so the
parser knows that it should interepret a bare "ismap" as ismap=ismap,
which gets you the same behavior in the end.

I think you could have figured out what I meant, but alright, replace
value with "enumeration value". the "alt" attribute isn't an enumeration,
and cannot be minimized.

the point is that SGML lets you say things like

"format can be one of A4, Letter, or Legal"

and then set the format simply by saying

<document letter>

on the other hand, this means that you cannot say things like

"paper can be one of A4, Letter, or Legal"
"pdf-size can be one of A4, Letter, or Legal"

and use minimization for these attributes.

(unless I'm missing some obscure corner of the spec, HTML only uses
attribute minimization for boolean attributes, so exactly how this is
done doesn't really matter. I'll better go *plonk* myself now...)

</F>
 
S

Steve Holden

Antoon said:
Op 2005-12-13, Chris Mellon schreef <[email protected]>: [...]
If you have a consistent API and you're checking for error values from
your GTK functions, then you already have a lot more code than using 2
varaibles will cost you. 10 lines, maybe.

The fact that you think setting two variables is "too hard" but you're
perfectly happy with checking for boolean types instead just testing
truth values I think is a real problem.


These aren't just truth values. If I would have to go split in
meaningfull truth values I would need at least three variables.

You aren't saving yourself any
performance. You're barely even saving yourself any typing, and you're
making your code (intentionally, it seems) that much more compllicated
and hard to understand.


There is nothing complicated or hard to understand.
Nope, just a messy, hard to maintain misuse of a single variable for
multiple purposes. Perfectly simple, perfectly easy to understand and
rather more bug-prone that a straightforward separation of state and
other data.
I find it odd that each time declaration are mentioned people here
react very rejecting and say that one of the features they love
about python is the freedom that a name is not limited to a variable
of one type, while when someone makes use of that freedom labeling
such code as code smell.
There's a difference between using a single name to refer to values of
polymorphic types (which can therefore all be handled by the same code)
and using the same name to reference state information in one case (this
item has no connected callback) and other data (the callback is to
such-and-such an object).
But lets make an effort to make the code more readable. What
about the following suggestion. I use a kind of EnumType with
two values: NotRegistered and Registerd. And the name of the
type is NotConnected. So I can then write

if type(self.callback) is NotConnected.

Would that be selfdocumenting enough for you?
It would be somewhat more self-documenting, but why not just use one
name to indicate the state and another, only meaningful in certain
states, to indicate the callback?

regards
Steve
 
S

Steven D'Aprano

Booleans are specifically defined as a subtype of int at the C level.

That's an implementation detail, and in fact an explicit decision made,
not a inescapable fact of programming. What you are saying is,
effectively, the point of having bools which are subclasses of ints is
that Guido wanted them that way.

One might also ask "what's the point of having floats if you can't tell
them from integers":

But you certainly can:

py> isinstance(True, int)
True
py> isinstance(0.0, int)
False

However, you can also ask:

py> isinstance(True, bool)
True
py> isinstance(1, bool)
False

or even:

py> type(True) == type(1)
False

but, I believe, using type() is frowned upon.
 
A

Antoon Pardon

Op 2005-12-13 said:
Antoon said:
Op 2005-12-13, Chris Mellon schreef <[email protected]>: [...]
If you have a consistent API and you're checking for error values from
your GTK functions, then you already have a lot more code than using 2
varaibles will cost you. 10 lines, maybe.

The fact that you think setting two variables is "too hard" but you're
perfectly happy with checking for boolean types instead just testing
truth values I think is a real problem.


These aren't just truth values. If I would have to go split in
meaningfull truth values I would need at least three variables.

You aren't saving yourself any
performance. You're barely even saving yourself any typing, and you're
making your code (intentionally, it seems) that much more compllicated
and hard to understand.


There is nothing complicated or hard to understand.
Nope, just a messy, hard to maintain misuse of a single variable for
multiple purposes.

No that variable has just one purpose, noting the state of the tube.
Perfectly simple, perfectly easy to understand and
rather more bug-prone that a straightforward separation of state and
other data.

What you call other date is IMO just state information.
There's a difference between using a single name to refer to values of
polymorphic types (which can therefore all be handled by the same code)
and using the same name to reference state information in one case (this
item has no connected callback) and other data (the callback is to
such-and-such an object).

It would be somewhat more self-documenting, but why not just use one
name to indicate the state and another, only meaningful in certain
states, to indicate the callback?

Why should I do that? Checking the type of a variable is conceptually
no different form testing set membership. So what I did, was just
bringing two disjoint sets togther and working with a variable from
that union. This is all in all a rather simple mathematical idea.
And I don't see why I should put certain information into a seperate
variable. It makes as much sense as working with numbers and using
a seperate variable to store whether a particular number is postive,
even or has some other characteristic. You don't seperate information
you can easily acquire from the variable itself. So why should I
seperate this information that is aquired just as easily?
 
S

Steve Holden

Antoon said:
Op 2005-12-13, Steve Holden schreef <[email protected]>: [...]
It would be somewhat more self-documenting, but why not just use one
name to indicate the state and another, only meaningful in certain
states, to indicate the callback?


Why should I do that? Checking the type of a variable is conceptually
no different form testing set membership. So what I did, was just
bringing two disjoint sets togther and working with a variable from
that union. This is all in all a rather simple mathematical idea.
And I don't see why I should put certain information into a seperate
variable. It makes as much sense as working with numbers and using
a seperate variable to store whether a particular number is postive,
even or has some other characteristic. You don't seperate information
you can easily acquire from the variable itself. So why should I
seperate this information that is aquired just as easily?

Well, as you might argue, I'm not tryng to effect a change in your
behaviour, I'm simply trying to point out how it could be made more
rational.

regards
Steve
 
B

bonono

Steve said:
Well, as you might argue, I'm not tryng to effect a change in your
behaviour, I'm simply trying to point out how it could be made more
rational.
What would be the difference in his usage and allowing Null in a RDBMS
column ? Or return NaN instead of raising exception for numeric
functions ?
 
A

Antoon Pardon

Op 2005-12-14 said:
Antoon Pardon wrote:

Well, as you might argue, I'm not tryng to effect a change in your
behaviour, I'm simply trying to point out how it could be made more
rational.

I guess we will just have to agree to disagree on what is more rational
in this case. Maybe it is just a case of what idiom one is used to.
 
G

Grant Edwards

What would be the difference in his usage and allowing Null in a RDBMS
column?

Don't know -- homey don't play 'dat.
Or return NaN instead of raising exception for numeric
functions ?

Because usually (in my applications anyway) NaN is a perfectly
valid value and not an "exception" case that needs to be handled.
 
A

Antoon Pardon

Op 2005-12-14 said:
Don't know -- homey don't play 'dat.


Because usually (in my applications anyway) NaN is a perfectly
valid value and not an "exception" case that needs to be handled.

I don't see the difference. In my application False and True
(or Registered and UnRegistered if you prefer) are perfectly valid
values too. They are not "exception" cases that need to be
handled.
 
G

Grant Edwards

Well, as you might argue, I'm not tryng to effect a change in
your behaviour, I'm simply trying to point out how it could be
made more rational. [...]
Or return NaN instead of raising exception for numeric
functions ?

Because usually (in my applications anyway) NaN is a perfectly
valid value and not an "exception" case that needs to be
handled.

I don't see the difference. In my application False and True
(or Registered and UnRegistered if you prefer) are perfectly
valid values too. They are not "exception" cases that need to
be handled.

Well, in my case, a given name (or return value) is always
bound to a floating point object. I don't test the type of the
object and treat it in two different ways depending on what
type it is. It's just a float.
 
M

Mike Meyer

What would be the difference in his usage and allowing Null in a RDBMS
column ? Or return NaN instead of raising exception for numeric
functions ?

Having a value to indicate "no value" is, of course, perfectly
reasonable. However, you then test *for that value*; you don't test
the type of the value to see if it's of the right type.

Once you get beyond the variable either having a valid value or not,
it's really time to consider a different approach. As has been
indicated, using two variables is ba well-respected method of doing
this. Another alternative (on the spur of the moment - I have no idea
how well this will really work) is a value-carrying "invalid value":

# untested code:
class Invalid:
state = 'unknown'

....

if self.count is Invalid:
if self.count.state == 'unregistered':
# Register self.
elif self.count.state == 'registered':
# Whatever
else:
# Deal with self.count outstanding requests

Hmm. I'm not sure I like this...

<mike
 
B

bonono

Mike said:
Having a value to indicate "no value" is, of course, perfectly
reasonable. However, you then test *for that value*; you don't test
the type of the value to see if it's of the right type.

Once you get beyond the variable either having a valid value or not,
it's really time to consider a different approach. As has been
indicated, using two variables is ba well-respected method of doing
this. Another alternative (on the spur of the moment - I have no idea
how well this will really work) is a value-carrying "invalid value":

# untested code:
class Invalid:
state = 'unknown'

...

if self.count is Invalid:
if self.count.state == 'unregistered':
# Register self.
elif self.count.state == 'registered':
# Whatever
else:
# Deal with self.count outstanding requests

Hmm. I'm not sure I like this...
He doesn't need to test the type, in this case.

if self.count is False:
elif self.count is True:
else:

The alternative suggested :

if self.state is False:
elif self.state is True:
else: deal with self.count

I don't see much difference. He can also use a better name to represent
True/False.

Registered=True
UnRegistered=False
 
A

Antoon Pardon

Op 2005-12-14 said:
Well, as you might argue, I'm not tryng to effect a change in
your behaviour, I'm simply trying to point out how it could be
made more rational. [...]
Or return NaN instead of raising exception for numeric
functions ?

Because usually (in my applications anyway) NaN is a perfectly
valid value and not an "exception" case that needs to be
handled.

I don't see the difference. In my application False and True
(or Registered and UnRegistered if you prefer) are perfectly
valid values too. They are not "exception" cases that need to
be handled.

Well, in my case, a given name (or return value) is always
bound to a floating point object. I don't test the type of the
object and treat it in two different ways depending on what
type it is. It's just a float.

Do you find that difference so important? As far as I understand
the gtk identifiers are always positive integers. So I could
have coded as follows:

UnConnected = (-1, -2)
Registered, UnRegistered = UnConnected

...

if self.cb_src in UnConnected:

Now all values are integers and I no longer treat an object different
depending on type but on value. However conceptually nothing changed.
My code branches depending on set membership of this attribute.

Could you explain why it should make a (big) difference between
these two approaches?
 
A

Antoon Pardon

Op 2005-12-14 said:
Having a value to indicate "no value" is, of course, perfectly
reasonable. However, you then test *for that value*; you don't test
the type of the value to see if it's of the right type.

Once you get beyond the variable either having a valid value or not,
it's really time to consider a different approach.

How do you feel about testing for set membership? I can have a set
with values to be treated differently than values not in the set.
Do you consider that an acceptable approach?
 
B

bonono

Antoon said:
Op 2005-12-14 said:
Well, as you might argue, I'm not tryng to effect a change in
your behaviour, I'm simply trying to point out how it could be
made more rational. [...]
Or return NaN instead of raising exception for numeric
functions ?

Because usually (in my applications anyway) NaN is a perfectly
valid value and not an "exception" case that needs to be
handled.

I don't see the difference. In my application False and True
(or Registered and UnRegistered if you prefer) are perfectly
valid values too. They are not "exception" cases that need to
be handled.

Well, in my case, a given name (or return value) is always
bound to a floating point object. I don't test the type of the
object and treat it in two different ways depending on what
type it is. It's just a float.

Do you find that difference so important? As far as I understand
the gtk identifiers are always positive integers. So I could
have coded as follows:

UnConnected = (-1, -2)
Registered, UnRegistered = UnConnected

...

if self.cb_src in UnConnected:

Now all values are integers and I no longer treat an object different
depending on type but on value. However conceptually nothing changed.
My code branches depending on set membership of this attribute.

Could you explain why it should make a (big) difference between
these two approaches?
That is what I would do in C or similar language where a variable can
only be one type.
 
G

Grant Edwards

Do you find that difference so important?

Possibly. In my case, a float is always a float. You can
always do the same set of operations on it.
As far as I understand
the gtk identifiers are always positive integers. So I could
have coded as follows:

UnConnected = (-1, -2)
Registered, UnRegistered = UnConnected

In your case, there isn't a single set of operations that work
regardles of the value. You have to _check_ the value in order
to decide what operations are allowed on that value. I'm not
saying the latter is "evil" but I think the distinction is
important.
...

if self.cb_src in UnConnected:

Now all values are integers and I no longer treat an object different
depending on type but on value. However conceptually nothing changed.
My code branches depending on set membership of this attribute.

Could you explain why it should make a (big) difference between
these two approaches?

Your examples are still both very different from the NaN
example. A NaN is a floating point operation that supports all
the same operations as all other floating point operations. In
your example an integer object of -2 does not support the same
"operations" that a "real" GTK identifier does. They are two
different types.
 
A

Antoon Pardon

Op 2005-12-15 said:
Possibly. In my case, a float is always a float. You can
always do the same set of operations on it.


In your case, there isn't a single set of operations that work
regardles of the value. You have to _check_ the value in order
to decide what operations are allowed on that value. I'm not
saying the latter is "evil" but I think the distinction is
important.


Your examples are still both very different from the NaN
example. A NaN is a floating point operation that supports all
the same operations as all other floating point operations. In
your example an integer object of -2 does not support the same
"operations" that a "real" GTK identifier does. They are two
different types.

I think the disctinction you are making is based on which level
you look at things. For you floats are something you use, you
see NaN as just a floats because the details of implementation
have been abstracted out for you.

But look at it from the level of someone who has to implement
floating point numbers. He can't just take two floats and put
them into his general add_float algorithm. If he did that
the result of working with a NaN could result in a regular
number. So he has to test for special values like NaN is
his 'code' too.

Of course we tend to forget this because in this case the
abstraction is usually done at the hardware level. But
I don't think that is such an important disctinction here.
 
G

Grant Edwards

I think the disctinction you are making is based on which level
you look at things.

Of course. I was looking at things from a Python point of view
since this is c.l.p.
For you floats are something you use, you see NaN as just a
floats because the details of implementation have been
abstracted out for you.

That goes without saying for anything in computer science or
electronics: it's all just quantum physics whose details of
implimentation have been abstracted out for me.
But look at it from the level of someone who has to implement
floating point numbers. He can't just take two floats and put
them into his general add_float algorithm. If he did that the
result of working with a NaN could result in a regular number.
So he has to test for special values like NaN is his 'code'
too.

Of course we tend to forget this because in this case the
abstraction is usually done at the hardware level. But I don't
think that is such an important disctinction here.

The distinction is in regards to readability and
maintainability of _Python_ code. This is comp.lang.python.
 

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,744
Messages
2,569,479
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top