Numbers and truth values

Discussion in 'Python' started by Szabolcs, Apr 28, 2007.

  1. Szabolcs

    Szabolcs Guest

    Newbie question:

    Why is 1 == True and 2 == True (even though 1 != 2),
    but 'x' != True (even though if 'x': works)?
     
    Szabolcs, Apr 28, 2007
    #1
    1. Advertising

  2. Szabolcs wrote:

    > Why is 1 == True and 2 == True (even though 1 != 2),


    Not what I get.

    Python 2.5 (r25:51908, Mar 13 2007, 08:13:14)
    [GCC 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)] on cygwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> 2 == True

    False
    --
    Michael Hoffman
     
    Michael Hoffman, Apr 28, 2007
    #2
    1. Advertising

  3. Szabolcs wrote:
    > Newbie question:
    >
    > Why is 1 == True and 2 == True (even though 1 != 2),
    > but 'x' != True (even though if 'x': works)?


    Please check before you post:

    [E:\Projects]python
    Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> 2==True

    False
    >>>


    Anyway,
    it helps to think about value domains (in your examples, numbers and strings)
    as having a single "null" value, and non-null values.
    The null value is considered False.
    The non-null values are considered True.

    The null value for numbers is 0 obviously, and for strings it is ''
    (the empty string).
    Non-zero numbers and non-empty strings are considered "True" when used
    in a boolean expression.

    --Irmen
     
    Irmen de Jong, Apr 28, 2007
    #3
  4. On Sat, 28 Apr 2007 14:33:23 +0200, Szabolcs wrote:

    > Newbie question:
    >
    > Why is 1 == True and 2 == True (even though 1 != 2),
    > but 'x' != True (even though if 'x': works)?


    Everything in Python has a truth-value. So you can always do this:

    if some_object:
    print "if clause is true"
    else:
    print "else clause"

    no matter what some_object is.

    The constants True and False are a pair of values of a special type bool.
    The bool type is in fact a sub-class of int:

    >>> issubclass(bool, int)

    True
    >>> 7 + False

    7
    >>> 7 + True

    8

    Can you guess what values True and False are "under the hood"?

    >>> 1 == True

    True
    >>> 0 == False

    True
    >>> 2 == True

    False
    >>> if 2:

    .... print "2 is considered true"
    ....
    2 is considered true


    If you are getting different results, the chances are that you have
    accidentally reassigned that names True or False:

    >>> True = 2 # DON'T DO THIS!!!
    >>> 2 == True

    True



    --
    Steven.
     
    Steven D'Aprano, Apr 28, 2007
    #4
  5. Szabolcs

    Szabolcs Guest

    Steven D'Aprano wrote:
    >
    >>>> 1 == True

    > True
    >>>> 0 == False

    > True
    >>>> 2 == True

    > False


    Oh my goodness! Now I also get 2 != True. I really don't know what
    happened. Most probably this (as a result of mistyping):

    >
    >>>> True = 2 # DON'T DO THIS!!!
    >>>> 2 == True

    > True
    >


    But shouldn't Python forbid this? Is it possible to get a warning when
    unintentionally redefining built-in thing?
     
    Szabolcs, Apr 28, 2007
    #5
  6. On Sat, 28 Apr 2007 15:36:19 +0200, Szabolcs wrote:

    >>>>> True = 2 # DON'T DO THIS!!!
    >>>>> 2 == True

    >> True
    >>

    >
    > But shouldn't Python forbid this? Is it possible to get a warning when
    > unintentionally redefining built-in thing?


    Python forbids very few things in comparison to other languages. The
    attitude is "We're all adults here". Because Python is such a dynamic
    language, it is often hard for the compiler to tell the difference between
    something you are doing deliberately and a mistake.

    If you're worried about that, google for PyChecker.


    --
    Steven.
     
    Steven D'Aprano, Apr 28, 2007
    #6
  7. Szabolcs <> wrote:
    ...
    > >>>> True = 2 # DON'T DO THIS!!!
    > >>>> 2 == True

    > > True

    >
    > But shouldn't Python forbid this? Is it possible to get a warning when
    > unintentionally redefining built-in thing?


    Python can be changed to make some non-reserved builtin identifiers into
    reserved words, going through a stage where this is allowed but gives a
    warning. This happened in recent years for assignments to None, which
    were legal back in 2.2 and earlier:

    $ python2.3 -c'None=23'
    <string>:1: SyntaxWarning: assignment to None
    $ python2.4 -c'None=23'
    File "<string>", line 1
    SyntaxError: assignment to None

    ....and, as you can see, gave syntax warnings in 2.3, becoming syntax
    errors in 2.4 and later versions.

    However, Python has a somewhat large and growing number of builtin
    identifiers:

    $ python2.3 -c'print len(__builtins__.__dict__)'
    124
    $ python2.4 -c'print len(__builtins__.__dict__)'
    128
    $ python2.5 -c'print len(__builtins__.__dict__)'
    133

    while keywords (reserved words) are far fewer, and more constrained in
    their growth:

    $ python2.3 -c'import keyword; print len(keyword.kwlist)'
    29
    $ python2.4 -c'import keyword; print len(keyword.kwlist)'
    29
    $ python2.5 -c'import keyword; print len(keyword.kwlist)'
    31

    so, making all builtins into keywords is unlikely to happen: it would
    break a lot of existing code in exchange for a minor benefit.

    It _would_ surely be possible to make Python behave this way only when a
    certain commandline flag or environment variable is present, e.g. by
    tweaking the implementation of the relevant bytecodes:

    >>> def f():

    .... global aglobal
    .... aglobal = 23
    .... alocal = 45
    ....
    >>> dis.dis(f)

    3 0 LOAD_CONST 1 (23)
    3 STORE_GLOBAL 0 (aglobal)

    4 6 LOAD_CONST 2 (45)
    9 STORE_FAST 0 (alocal)
    12 LOAD_CONST 0 (None)
    15 RETURN_VALUE

    STORE_GLOBAL and STORE_FAST. However, this might slow down normal
    operation (by needing to check some flag at each STORE_...).

    Perhaps a better approach is to perform your checking with a tool that
    is _separate_ from "Python proper". Wouldn't it be great to have a tool
    to check Python sources, one which we could name, for example,
    pychecker, that we could run as follows...:

    $ cat >ba.py
    False = 23

    $ pychecker ba.py
    Processing ba...

    Warnings...

    ba.py:1: (False) shadows builtin
    ba.py:1: Should not assign to False, it is (or will be) a builtin


    Rejoyce! <http://pychecker.sourceforge.net/> ...

    There are other tools to perform such checks, such as pylint,
    <http://www.logilab.org/857>, which is quite a bit more complicated but
    can perform many more checks (and can be integrated into PyDev, an
    Eclipse add-on which some people like to use as a Python IDE), and, I
    believe, a few other with slightly different slants (such as pyflakes,
    <http://www.divmod.org/projects/pyflakes>, which does fewer checks but
    does them faster and in a way that's safe against potentially-evil
    code).

    By the way, both of these tools (and many other tools, and a lot of
    other useful tips) are mentioned at
    <http://www.python.org/doc/faq/programming/> , the Python Programming
    FAQ (it's a bit dated, but if you find any problem with it, just like
    with any other piece of official Python docs, bugs and suggested patches
    are welcome at the usual location,
    <http://sourceforge.net/projects/python> ).

    Perhaps one day some variant of pychecker and/or pylint can be
    integrated in Python itself, and executed (for example at each import)
    if that's indicated by some appropriate flag or environment variable;
    however, for us command-line dinosaurs, the people who prefer running
    python at a shell prompt (rather than more advanced things such as
    ipython, or IDEs such as PyDev, IDLE, etc, etc) this doesn't really tend
    to be that high a priority, as we're quite used to "not necessarily
    auto-integrated" tools; it's probably a higher priority to get pychecker
    or something like that integrated with other IDEs such as IDLE (I don't
    know, besides PyDev's ability to use pylint, which other such
    integrations currently exist -- anybody?).


    Alex
     
    Alex Martelli, Apr 28, 2007
    #7
  8. Szabolcs

    John Nagle Guest

    Steven D'Aprano wrote:
    > On Sat, 28 Apr 2007 15:36:19 +0200, Szabolcs wrote:
    >
    >
    >>>>>>True = 2 # DON'T DO THIS!!!
    >>>>>>2 == True
    >>>
    >>>True
    >>>

    >>
    >>But shouldn't Python forbid this? Is it possible to get a warning when
    >>unintentionally redefining built-in thing?

    >
    >
    > Python forbids very few things in comparison to other languages. The
    > attitude is "We're all adults here". Because Python is such a dynamic
    > language, it is often hard for the compiler to tell the difference between
    > something you are doing deliberately and a mistake.


    I'd have to consider that a bug.

    Some very early FORTRAN compilers allowed you to redefine
    integer constants:


    CALL SET(25,99)
    WRITE (6,100) 25
    100 FORMAT(I6)

    SUBROUTINE SET(IVAR, INEWVAL)
    IVAR = INEWVAL

    would print

    99

    It was generally agreed by 1970 or so that this was a bad idea,
    and was taken out of the language.

    C originally didn't have a Boolean type, and it took years to
    get that in and uniformly defined. But in the end, "true" and
    "false" were reserved words.

    "True", "False", and "None" should be reserved words in Python.
    "None" already is.

    John Nagle
     
    John Nagle, Apr 28, 2007
    #8
  9. John Nagle <> wrote:
    ...
    > I'd have to consider that a bug.
    >
    > Some very early FORTRAN compilers allowed you to redefine
    > integer constants:
    >
    >
    > CALL SET(25,99)
    > WRITE (6,100) 25
    > 100 FORMAT(I6)
    >
    > SUBROUTINE SET(IVAR, INEWVAL)
    > IVAR = INEWVAL
    >
    > would print
    >
    > 99
    >
    > It was generally agreed by 1970 or so that this was a bad idea,
    > and was taken out of the language.


    It was still perfectly legal in the Fortran 1977 standard for a compiler
    to cause this effect, because the Fortran source you quote has
    *undefined behavior* -- the compiler doesn't have to diagnose this error
    and can cause any effects as a consequence.

    The point of Fortran is to let the compiler generate the fastest code it
    can, NOT to "tenderly hold your hand" lest scary bugs disturb your
    blessed and dreamy innocence.

    If this has changed in the Fortran 1990 standard or later, then I can
    only say I'm happy I stopped using Fortran heavily before such standards
    became widespread in commonly available compilers -- by the late '90s,
    when I was still using _some_ Fortran, it was Fortran '77, as that was
    the version that was widely available and well optimized.

    Python is not particularly focused on coddling the programmer lest he or
    she (horrors!) make a mistake, either; rather, it embodies well 4 of the
    5 principles that make up the "Spirit of C" according to the Preface to
    C's ISO Standard -- "trust the programmer", "don't stop the programmer
    from doing what needs to be done", "keep the language small and simple"
    (the 4th one, "offer only one way to perform an operation", is not
    germane here). Making the language more complicated (e.g., with more
    reserved words) because you _don't_ trust the programmer and badly wants
    to stop him/her from doing something is not well consistent with these
    principles. Maybe somebody assigning a value to True or False is a
    common error, but much of my livelihood over the last 10 years has been
    about mentoring/coaching programmers in Python, and that's one error I
    have *NEVER* observed, so I'd need a lot of empirical evidence to
    convince me it's worth adding two more reserved words to Python's
    reasonably short list (I feel much the same way about None, by the way).
    pychecker, pylint, and friends, are a much better way to detect and warn
    about all sort of anomalies of this kind.


    Alex
     
    Alex Martelli, Apr 28, 2007
    #9
  10. Szabolcs

    Szabolcs Guest

    Alex Martelli wrote:
    > Maybe somebody assigning a value to True or False is a
    > common error, but much of my livelihood over the last 10 years has been
    > about mentoring/coaching programmers in Python, and that's one error I
    > have *NEVER* observed, so I'd need a lot of empirical evidence to
    > convince me it's worth adding two more reserved words to Python's
    > reasonably short list (I feel much the same way about None, by the way).
    > pychecker, pylint, and friends, are a much better way to detect and warn
    > about all sort of anomalies of this kind.


    Yes, I admit that it was a very stupid mistake. (Though I'm not even
    sure that this is what happened. Next time I should probably sleep on
    it, and try it again the next day, to avoid posting such a stupid
    question again.) But note that I was using Python interactively (just
    experimenting with it). It is very unlikely that someone would write
    things like True == 2 without any additional context in a real program.
    (Actually it is unlikely that someone would write this in any
    circumstance in a real program.)

    But I still think that it is an inconsistency to allow to redefine a
    _value_ like True or False (not a built-in function that may have been
    missing in earlier versions). Saying True = 2 is just like saying 3 = 2.

    Learning about pylint was very useful (thanks for the advice!) -- it
    helps in catching those kinds of errors that surface only at runtime in
    Python programs, but are easily caught at compile time in compiled
    languages.
     
    Szabolcs, Apr 28, 2007
    #10
  11. Szabolcs

    Mel Wilson Guest

    John Nagle wrote:
    > "True", "False", and "None" should be reserved words in Python.
    > "None" already is.


    The permissiveness makes it less painful to upgrade to new versions of
    Python. True and False only recently got assigned conventional
    values, but you can still import old modules without worrying whether
    they might violate the new rule; if True and False once meant
    something special to them, it will still mean the same thing.

    Meanwhile new code can follow the new conventions.



    Mel.
     
    Mel Wilson, Apr 29, 2007
    #11
  12. On Sat, 28 Apr 2007 11:35:36 -0700, John Nagle wrote:

    >> Python forbids very few things in comparison to other languages. The
    >> attitude is "We're all adults here". Because Python is such a dynamic
    >> language, it is often hard for the compiler to tell the difference between
    >> something you are doing deliberately and a mistake.

    >
    > I'd have to consider that a bug.


    [snip]

    > "True", "False", and "None" should be reserved words in Python.
    > "None" already is.


    What are you going to do about the code that pre-dates the introduction of
    bools that defines

    False = 0
    True = not False

    at the start of the module? The Python philosophy is to break existing
    code as little as possible (at least until Python 3).



    --
    Steven
     
    Steven D'Aprano, Apr 29, 2007
    #12
  13. On Sat, 28 Apr 2007 23:54:01 +0200, Szabolcs wrote:

    > But I still think that it is an inconsistency to allow to redefine a
    > _value_ like True or False (not a built-in function that may have been
    > missing in earlier versions). Saying True = 2 is just like saying 3 = 2.


    Well, it might seem that way, but it isn't really. It's more like having
    built-in names

    One = 1
    Zero = 0

    (plus some special code so that when you say "print One" it prints
    "One" rather than 1) in Python. You wouldn't be surprised to be able to
    redefine One = 2 there, would you?

    The ability to shadow built-ins is a fact of life in the Python world.
    Python has a lot of built-ins, and very few keywords, and that situation
    is unlikely to change. As Alex explained, the philosophy is not to slow
    the compiler and interpreter down with checks against those sort of
    problems directly, but to trust the programmer to call external tools like
    pylint and pychecker if they want. It may be that True and False will
    (like None before it) be moved from the built-ins category into the
    keyword category, but I don't think that's the most pressing problem in
    Python.



    --
    Steven.
     
    Steven D'Aprano, Apr 29, 2007
    #13
  14. Szabolcs <> wrote:

    > But I still think that it is an inconsistency to allow to redefine a
    > _value_ like True or False (not a built-in function that may have been
    > missing in earlier versions). Saying True = 2 is just like saying 3 = 2.


    True and False were *ALSO* missing in earlier versions of Python (2.2.1
    and back -- they were introduced in 2.2.2, smack in the middle of a
    minor release cycle, a release engineering error which Guido has vowed
    never to repeat).

    There's a lot of code around that starts with

    False = 0
    True = not False

    (or similar), so it can run just as well on (e.g) 2.2.1 (and earlier) as
    2.2.2 (and later) -- breaking all of that code which always worked fine
    is a decision not to be taken as lightly as you appear to imply.


    Alex
     
    Alex Martelli, Apr 29, 2007
    #14
  15. Szabolcs

    Beliavsky Guest

    On Apr 28, 4:05 pm, (Alex Martelli) wrote:
    > John Nagle <> wrote:
    >
    > > I'd have to consider that a bug.

    >
    > > Some very early FORTRAN compilers allowed you to redefine
    > > integer constants:

    >
    > > CALL SET(25,99)
    > > WRITE (6,100) 25
    > > 100 FORMAT(I6)

    >
    > > SUBROUTINE SET(IVAR, INEWVAL)
    > > IVAR = INEWVAL

    >
    > > would print

    >
    > > 99

    >
    > > It was generally agreed by 1970 or so that this was a bad idea,
    > > and was taken out of the language.

    >
    > It was still perfectly legal in the Fortran 1977 standard for a compiler
    > to cause this effect, because the Fortran source you quote has
    > *undefined behavior* -- the compiler doesn't have to diagnose this error
    > and can cause any effects as a consequence.
    >
    > The point of Fortran is to let the compiler generate the fastest code it
    > can, NOT to "tenderly hold your hand" lest scary bugs disturb your
    > blessed and dreamy innocence.


    The point of Fortran has been to make scientific programmers more
    productive, and catching errors and producing fast programs are BOTH
    ways of doing that. Compilers are judged on BOTH criteria:
    speed: http://www.polyhedron.com/pb05/linux/f90bench_p4.html
    diagnostics: http://www.polyhedron.com/pb05/linux/diagnose.html

    If there is a compiler with great compile- and run-time debugging
    capability with the right options turned on, and if the compiler also
    produces optimally fast code with another set of options (or if
    another compiler does this), isn't that the best of both worlds?

    > If this has changed in the Fortran 1990 standard or later, then I can
    > only say I'm happy I stopped using Fortran heavily before such standards
    > became widespread in commonly available compilers -- by the late '90s,
    > when I was still using _some_Fortran, it was Fortran '77, as that was
    > the version that was widely available and well optimized.


    I don't think the official status of such has changed -- it's still
    illegal to change a constant and the compiler is still not required to
    catch the error -- but compilers may be more likely to reject
    such code as before, helping programmers spot errors. IMO that's a
    good thing.

    When is no longer using a language, one has the luxury of thinking
    about it in an ideological rather than practical manner.
     
    Beliavsky, Apr 29, 2007
    #15
  16. Beliavsky <> wrote:
    ...
    > > If this has changed in the Fortran 1990 standard or later, then I can
    > > only say I'm happy I stopped using Fortran heavily before such standards
    > > became widespread in commonly available compilers -- by the late '90s,
    > > when I was still using _some_Fortran, it was Fortran '77, as that was
    > > the version that was widely available and well optimized.

    >
    > I don't think the official status of such has changed -- it's still
    > illegal to change a constant and the compiler is still not required to
    > catch the error


    Oh good -- I'm happy to hear that the original spirit IS still around.

    > -- but compilers may be more likely to reject
    > such code as before, helping programmers spot errors. IMO that's a
    > good thing.


    In general, as an engineer, I think that making tools more complicated
    so that a single tool can serve multiple purposes is not necessarily a
    win. I do not want one pair of shoes that are designed to be excellent
    for running AND for dancing AND for mountain hiking: I'd much rather
    have three specialized pairs of shoes instead, one pair for running, one
    for dancing, one for hiking.

    Similarly, I'd rather have one tool to take presumably-correct sources
    and generate great machine code from them, and separate tools to nitpick
    the bejeezus out of the sources to make really sure they ARE indeed
    perfectly correct from all viewpoints. Two (or more) simple, fully
    specialized tools make for a better toolbox than one complex,
    multi-purpose one. Few except engineers seem to understand this.

    > When is no longer using a language, one has the luxury of thinking
    > about it in an ideological rather than practical manner.


    I thought about Fortran in exactly the same way when I was doing most of
    my coding in it, and also using it to teach "numerical computing" in
    university. Most errors came (and still come) from people who just
    don't understand the underlying mathematical nature and realities of
    floating point (and numerical computations more generally), and I never
    expected a compiler to magically start warning the user about "you're
    using a very badly conditioned algorithm for this computation":), the
    one thing that would have really saved me a lot of time in my advisory
    and teaching roles. Exactly the same problems keep surfacing in
    programs in Python and any other language too, barely veiled by today's
    growing propensity for double-precision and wider-yet floats; offering a
    rich library of functions is NOT a viable replacement for understanding
    and approaching computation correctly (users will just call extremely
    general library functions, rather than understand their problem's
    specific "geometries" and address them appropriately).

    (Let me offer one more plug for my favorite "book about programming
    without a single line of code in it", Foreman Acton's "Real computing
    made real", now out in a wonderfully cheap Dover edition: Acton makes
    this case better than I've ever seen it made elsewhere, and offers many
    excellent examples of how numerical computation SHOULD be done).


    Alex
     
    Alex Martelli, Apr 30, 2007
    #16
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. shibu

    Truth Table Implementation

    shibu, Aug 24, 2003, in forum: VHDL
    Replies:
    3
    Views:
    4,960
    Mario Trams
    Sep 4, 2003
  2. Replies:
    1
    Views:
    707
    =?Utf-8?B?Q3VydF9DIFtNVlBd?=
    Oct 12, 2005
  3. lyallex
    Replies:
    14
    Views:
    629
    Chris Smith
    Nov 24, 2004
  4. Henry

    The truth about css and W3C

    Henry, Jan 6, 2005, in forum: HTML
    Replies:
    2
    Views:
    388
    Henry
    Jan 6, 2005
  5. Mario

    Truth Table

    Mario, Jul 9, 2003, in forum: C++
    Replies:
    2
    Views:
    701
    John Harrison
    Jul 10, 2003
Loading...

Share This Page