Attack a sacred Python Cow

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Heiko Wundram

    Re: Boolean tests [was Re: Attack a sacred Python Cow]

    Am Dienstag, 29. Juli 2008 10:37:45 schrieb Carl Banks:
    You keep bringing up this notion of "more complex with no benefit",
    which I'm simply not interested in talking about that at this time,
    and I won't respond to any of your points. I am seeking the answer to
    one question: whether "if x" can usefully do something a simple
    explicit test can't. Everyone already knows that "if x" requires
    fewer keystrokes and parses to fewer nodes.
    Yes, there are quite a lot of use cases. Think of a polymorphic function,
    where the input can be any object that implements the iterator protocol
    (concerning base types, I'm thinking of strings, tuples, lists, dicts and
    sets here, which are all iterable and yield a chain of singular values) and
    you want to check whether the iterable object is empty or not for
    special-casing that.

    "if x" uses the special interface method __nonzero__() if that's implemented
    (which all of the above types implement as returning True iff the container
    yields at least one value when iterated over, i.e., it isn't empty), and
    falls back to a test for __len__() != 0, otherwise x is considered to be
    true.

    Now, explicitly comparing x against the five "empty" values of the container
    types I specified above would be broken design in such a function: when I
    implement a container class myself, which implements the __iter__() and
    __nonzero__() methods, I can directly use it with the polymorphic function I
    wrote, and the special case for an empty container will work out of the box.
    In the case of explicit comparisons, I have to modify the polymorphic
    function to accept my container type in addition to those it already
    processes to be able to special-case the empty container for my type.

    I can't dig up a simple example from code I wrote quickly, but because of the
    fact that explicit comparisons always hamper polymorphism (which might not be
    needed initially, but you never know what comes up later, thinking of
    reusability of components), I personally always stick to the idiom "if x"
    rather than comparing it to an empty value, even when I'm sure that the type
    of x is a singular type.

    Additionally, IMHO "if x" is so much more readable than "if x != <something>".

    Just my 2 (euro)cents.

    --
    Heiko Wundram

    Comment

    • Steven D'Aprano

      Re: Boolean tests [was Re: Attack a sacred Python Cow]

      On Tue, 29 Jul 2008 01:37:45 -0700, Carl Banks wrote:
      On Jul 28, 8:15 pm, Steven D'Aprano <st...@REMOVE-THIS-
      cybersource.com .auwrote:
      >On Mon, 28 Jul 2008 13:22:37 -0700, Carl Banks wrote:
      On Jul 28, 10:00 am, Steven D'Aprano <st...@REMOVE-THIS-
      cybersource.com .auwrote:
      >Cutting to the crux of the discussion...
      >>
      >On Sun, 27 Jul 2008 23:45:26 -0700, Carl Banks wrote:
      I want something where "if x" will do but a simple explicit test
      won't.
      >>
      >Explicit tests aren't simple unless you know what type x is. If x
      >could be of any type, you can't write a simple test. Does x have a
      >length? Is it a number? Maybe it's a fixed-length circular length,
      >and the length is non-zero even when it's empty? Who knows? How many
      >cases do you need to consider?
      >>
      Use case, please. I'm asking for code, not arguments. Please give
      me a piece of code where you can write "if x" that works but a simple
      explicit test won't.
      >>
      >I gave you a piece of code, actual code from one of my own projects. If
      >you wouldn't accept that evidence then, why would you accept it now?
      >
      I would accept as "evidence" something that satisfies my criteria, which
      your example did not: it could have easily (and more robustly) been
      written with a simple explicit test.
      Only at the cost of completely ignoring the functional requirements and
      changing the API. In other words: you ignore my code, and invent your own
      imaginary code that does something completely different, then say that
      this imaginary code is better.

      And I question your assertion that a "simple explicit test" is more
      robust. Where's your evidence for that?


      I am looking for one that can't.
      If you are writing code that needs to do the right thing with arbitrary
      types, then your so-called "simple explicit tests" simply can't work. If
      your code isn't expected to deal with arbitrary types, then you've got an
      excellent chance that it will work, because you know what types to expect.

      Until somebody passes a type that you didn't expect, and your code fails
      because it makes assumptions about the object.

      If you know that you only get lists, then "if len(x)!=0" is a perfectly
      good test (apart from being longer to type, harder to read, and slower to
      execute than "if x"). It will work so long as you only get objects where
      a length of zero is equivalent to being false. That's a good assumption
      to make, but it is an *unnecessary* assumption. Any reasonable object you
      get will know if it is false/nothing or true/something, so why make any
      assumptions? Just ask the object. It knows.


      You keep bringing up this notion of "more complex with no benefit",
      which I'm simply not interested in talking about that at this time, and
      I won't respond to any of your points.
      Of course not.


      I am seeking the answer to one
      question: whether "if x" can usefully do something a simple explicit
      test can't.
      "if x" is completely type agnostic. You can pass an object of any type to
      it, and it will work. (Excluding objects with buggy methods, naturally.)

      Try doing that with one of your so-called "simple explicit tests".



      --
      Steven

      Comment

      • Anders J. Munch

        Re: Boolean tests [was Re: Attack a sacred Python Cow]

        Steven D'Aprano wrote:
        On Tue, 29 Jul 2008 00:23:02 +0000, Steven D'Aprano wrote:
        >
        >Dude. Dude. Just... learn some Python before you embarrass yourself
        >further.
        >
        >
        I'm sorry Anders, that was a needlessly harsh thing for me to say. I
        apologize for the unpleasant tone.
        >
        Still, __nonzero__ is a fundamental part of Python's behaviour. You
        should learn about it.
        Hm, first you apologize, then you repeat the insult? That's no basis for a
        conversation. Bye from here.

        regards, Anders

        Comment

        • Heiko Wundram

          Re: Boolean tests [was Re: Attack a sacred Python Cow]

          Am Dienstag, 29. Juli 2008 11:15:05 schrieb Heiko Wundram:
          I can't dig up a simple example from code I wrote quickly...
          Just to get back to that: an example I found where "if x" (the generic
          __nonzero__() test) will work to test for emptiness/non-emptiness of a
          container, whereas "if len(x) 0" (the "specific" test for this example)
          will not, is my for own integer set type I wrote a while back (which you can
          find on ASPN).

          The corresponding set type allows you to create infinitely sized sets of
          integers (which of course are stored as pairs of <start>,<stop >-values, so
          the storage itself for the set is bounded), for which len(x) does not have
          a "proper" meaning anymore, and __len__() is limited to returning a (platform
          dependent) ssize_t anyway IIRC, so even with a bounded set, the length of the
          set might not necessarily be accessible using len(x); that's why the set type
          additionally got a member function called .len() to work around this
          restriction.

          I should think is a non-contrieved example where the generic test whether the
          object considers itself True/False (which for containers means
          non-empty/empty) is preferrable over the special case test whether the length
          is positive. A polymorphic function, which for example only accesses the
          first ten members of the container is able to work with an infinite set if it
          uses the generic test, but is not in case it uses len(x) 0.

          --
          Heiko Wundram

          Comment

          • Ben Finney

            Re: Boolean tests

            "Anders J. Munch" <2007@jmunch.dk writes:
            Steven D'Aprano wrote:
            I'm sorry Anders, that was a needlessly harsh thing for me to say.
            I apologize for the unpleasant tone.

            Still, __nonzero__ is a fundamental part of Python's behaviour.
            You should learn about it.
            >
            Hm, first you apologize, then you repeat the insult? That's no basis
            for a conversation. Bye from here.
            No, he retracted the *insult* and restated the *advice* as a distinct
            statement. I think it's quite worthwhile to help people see the
            difference.

            --
            \ “People are very open-minded about new things, as long as |
            `\ they're exactly like the old ones.” —Charles F. Kettering |
            _o__) |
            Ben Finney

            Comment

            • Colin J. Williams

              Re: Boolean tests [was Re: Attack a sacred Python Cow]

              Heiko Wundram wrote:
              Am Dienstag, 29. Juli 2008 11:15:05 schrieb Heiko Wundram:
              >I can't dig up a simple example from code I wrote quickly...
              >
              Just to get back to that: an example I found where "if x" (the generic
              __nonzero__() test) will work to test for emptiness/non-emptiness of a
              container, whereas "if len(x) 0" (the "specific" test for this example)
              will not, is my for own integer set type I wrote a while back (which you can
              find on ASPN).
              >
              The corresponding set type allows you to create infinitely sized sets of
              integers (which of course are stored as pairs of <start>,<stop >-values, so
              the storage itself for the set is bounded), for which len(x) does not have
              a "proper" meaning anymore, and __len__() is limited to returning a (platform
              dependent) ssize_t anyway IIRC, so even with a bounded set, the length of the
              set might not necessarily be accessible using len(x); that's why the set type
              additionally got a member function called .len() to work around this
              restriction.
              >
              I should think is a non-contrieved example where the generic test whether the
              object considers itself True/False (which for containers means
              non-empty/empty) is preferrable over the special case test whether the length
              is positive. A polymorphic function, which for example only accesses the
              first ten members of the container is able to work with an infinite set if it
              uses the generic test, but is not in case it uses len(x) 0.
              >
              (+1) This an Heiko's previous post sets
              things out clearly.

              Colin W.

              Comment

              • Matthew Fitzgibbons

                Re: Boolean tests [was Re: Attack a sacred Python Cow]

                Carl Banks wrote:
                On Jul 28, 8:15 pm, Steven D'Aprano <st...@REMOVE-THIS-
                cybersource.com .auwrote:
                >On Mon, 28 Jul 2008 13:22:37 -0700, Carl Banks wrote:
                >>On Jul 28, 10:00 am, Steven D'Aprano <st...@REMOVE-THIS-
                >>cybersource.c om.auwrote:
                >>>Cutting to the crux of the discussion...
                >>>On Sun, 27 Jul 2008 23:45:26 -0700, Carl Banks wrote:
                >>>>I want something where "if x" will do but a simple explicit test
                >>>>won't.
                >>>Explicit tests aren't simple unless you know what type x is. If x could
                >>>be of any type, you can't write a simple test. Does x have a length? Is
                >>>it a number? Maybe it's a fixed-length circular length, and the length
                >>>is non-zero even when it's empty? Who knows? How many cases do you need
                >>>to consider?
                >>Use case, please. I'm asking for code, not arguments. Please give me a
                >>piece of code where you can write "if x" that works but a simple
                >>explicit test won't.
                >I gave you a piece of code, actual code from one of my own projects. If
                >you wouldn't accept that evidence then, why would you accept it now?
                >
                I would accept as "evidence" something that satisfies my criteria,
                which your example did not: it could have easily (and more robustly)
                been written with a simple explicit test. I am looking for one that
                can't.
                >
                You keep bringing up this notion of "more complex with no benefit",
                which I'm simply not interested in talking about that at this time,
                and I won't respond to any of your points. I am seeking the answer to
                one question: whether "if x" can usefully do something a simple
                explicit test can't. Everyone already knows that "if x" requires
                fewer keystrokes and parses to fewer nodes.
                >
                >
                Carl Banks
                --

                >
                My use case involves a DAG of filters that pass data (of a variety of
                types--filters just pass on data types they don't understand) between
                them. I can also drop out of the filter chain at any point, using
                critera determined by the filters. These criteria, you guessed it, are
                bound to __nonzero__ in the filter and I determine whether or not to
                continue through the graph using "if x". You can't code explicit tests
                if you don't know what the tests even are beforehand. Also, I wanted to
                support builtins (ints and lists in particular) because they can be
                meaningful inputs to filters. Finally, as I add more filters and data
                types, I don't want to go back and mess with the code that decides
                whether or not to break out of the graph.

                -Matt

                Comment

                • Carl Banks

                  Re: Boolean tests [was Re: Attack a sacred Python Cow]

                  On Jul 29, 5:27 am, Steven D'Aprano
                  <ste...@REMOVE. THIS.cybersourc e.com.auwrote:
                  On Tue, 29 Jul 2008 01:37:45 -0700, Carl Banks wrote:
                  I am looking for one that can't.
                  >
                  If you are writing code that needs to do the right thing with arbitrary
                  types, then your so-called "simple explicit tests" simply can't work.
                  I asked for a code example. You say this is true, but neither you nor
                  anyone else here has provided useful code that demonstrates it.


                  Carl Banks

                  Comment

                  • Carl Banks

                    Re: Boolean tests [was Re: Attack a sacred Python Cow]

                    On Jul 29, 5:15 am, Heiko Wundram <modeln...@mode lnine.orgwrote:
                    I can't dig up a simple example from code I wrote quickly, but because of the
                    fact that explicit comparisons always hamper polymorphism
                    I'm not going to take your word for it. Do you have code that
                    demonstrates how "if x" improves polymorphism relative to simple
                    explicit tests?


                    Carl Banks

                    Comment

                    • Carl Banks

                      Re: Boolean tests [was Re: Attack a sacred Python Cow]

                      On Jul 29, 11:12 am, Matthew Fitzgibbons <eles...@nienna .orgwrote:
                      Carl Banks wrote:
                      On Jul 28, 8:15 pm, Steven D'Aprano <st...@REMOVE-THIS-
                      cybersource.com .auwrote:
                      On Mon, 28 Jul 2008 13:22:37 -0700, Carl Banks wrote:
                      >On Jul 28, 10:00 am, Steven D'Aprano <st...@REMOVE-THIS-
                      >cybersource.co m.auwrote:
                      >>Cutting to the crux of the discussion...
                      >>On Sun, 27 Jul 2008 23:45:26 -0700, Carl Banks wrote:
                      >>>I want something where "if x" will do but a simple explicit test
                      >>>won't.
                      >>Explicit tests aren't simple unless you know what type x is. If x could
                      >>be of any type, you can't write a simple test. Does x have a length? Is
                      >>it a number? Maybe it's a fixed-length circular length, and the length
                      >>is non-zero even when it's empty? Who knows? How many cases do you need
                      >>to consider?
                      >Use case, please. I'm asking for code, not arguments. Please give me a
                      >piece of code where you can write "if x" that works but a simple
                      >explicit test won't.
                      I gave you a piece of code, actual code from one of my own projects. If
                      you wouldn't accept that evidence then, why would you accept it now?
                      >
                      I would accept as "evidence" something that satisfies my criteria,
                      which your example did not: it could have easily (and more robustly)
                      been written with a simple explicit test. I am looking for one that
                      can't.
                      >
                      You keep bringing up this notion of "more complex with no benefit",
                      which I'm simply not interested in talking about that at this time,
                      and I won't respond to any of your points. I am seeking the answer to
                      one question: whether "if x" can usefully do something a simple
                      explicit test can't. Everyone already knows that "if x" requires
                      fewer keystrokes and parses to fewer nodes.
                      >>
                      My use case involves a DAG of filters that pass data (of a variety of
                      types--filters just pass on data types they don't understand) between
                      them. I can also drop out of the filter chain at any point, using
                      critera determined by the filters. These criteria, you guessed it, are
                      bound to __nonzero__ in the filter and I determine whether or not to
                      continue through the graph using "if x". You can't code explicit tests
                      if you don't know what the tests even are beforehand. Also, I wanted to
                      support builtins (ints and lists in particular) because they can be
                      meaningful inputs to filters. Finally, as I add more filters and data
                      types, I don't want to go back and mess with the code that decides
                      whether or not to break out of the graph.
                      Much like in Steven D'Aprano's example, still the only actual code
                      snippet I've seen, it seems that this can easily be done with a simple
                      explicit test by having all no-advance filters return None and testing
                      with "if x is not None". So it doesn't pass my criterion of being not
                      replaceable with simple explicit test.

                      Maybe that's not workable for some reason. Perhaps if you'd post a
                      code example that shows this, rather than just talking about it, you
                      might be more persuasive.


                      Carl Banks

                      Comment

                      • Carl Banks

                        Re: Boolean tests [was Re: Attack a sacred Python Cow]

                        On Jul 29, 1:30 pm, Carl Banks <pavlovevide... @gmail.comwrote :
                        On Jul 29, 5:15 am, Heiko Wundram <modeln...@mode lnine.orgwrote:
                        >
                        I can't dig up a simple example from code I wrote quickly, but because of the
                        fact that explicit comparisons always hamper polymorphism
                        >
                        I'm not going to take your word for it. Do you have code that
                        demonstrates how "if x" improves polymorphism relative to simple
                        explicit tests?
                        And, in case it wasn't obvious, the way to demonstrate that "if x"
                        improves polymorphism relative to simple explicit tests would be
                        posting an example where "if x" works but a simple explicit test
                        doesn't. So don't accuse me of changing the question on you: it's the
                        same question.

                        You see, what you are stating and expecting me to take for granted is
                        exactly what I'm asking for a concrete example of.


                        Carl Banks

                        Comment

                        • Carl Banks

                          Re: Boolean tests [was Re: Attack a sacred Python Cow]

                          On Jul 29, 5:27 am, Steven D'Aprano
                          <ste...@REMOVE. THIS.cybersourc e.com.auwrote:
                          On Tue, 29 Jul 2008 01:37:45 -0700, Carl Banks wrote:
                          I would accept as "evidence" something that satisfies my criteria, which
                          your example did not: it could have easily (and more robustly) been
                          written with a simple explicit test.
                          >
                          Only at the cost of completely ignoring the functional requirements and
                          changing the API. In other words: you ignore my code, and invent your own
                          imaginary code that does something completely different, then say that
                          this imaginary code is better.
                          And, BTW, you keep making unsubstantiated assertions and keep
                          expecting me to take them at face value. I'm really not going to take
                          your word for it that your "functional requirements" would preclude
                          the possibility of rewriting it as I said to, unless you provide
                          details.

                          Also, your third claim is false since it would have exactly the same
                          behavior.


                          Carl Banks

                          Comment

                          • Terry Reedy

                            Re: Attack a sacred Python Cow



                            Nikolaus Rath wrote:
                            Bruno Desthuilliers <bdesth.quelque chose@free.quel quepart.frwrite s:
                            >Nikolaus Rath a écrit :
                            >>Thats true. But out of curiosity: why is changing the interpreter such
                            >>a bad thing? (If we suppose for now that the change itself is a good
                            >>idea).
                            >Because it would very seriously break a *lot* of code ?
                            >
                            Well, Python 3 will break lots of code anyway, won't it?
                            Each code breaking change was evaluated as a cost against the long-term
                            net benefits. Many are removals that were announced years ago and which
                            will not break code written with an eye to the future. An example is
                            the removal of 'apply', which was replace with '*iterable' years ago.

                            Some proposed changes, were rejected only because they would break too
                            much code, or because automatic fixed would not be easy. For these
                            reasons, the core Python syntax is pretty much untouched. Attribute
                            lookup is part of core syntax.

                            Comment

                            • Erik Max Francis

                              Re: Boolean tests [was Re: Attack a sacred Python Cow]

                              Carl Banks wrote:
                              On Jul 29, 1:30 pm, Carl Banks <pavlovevide... @gmail.comwrote :
                              >On Jul 29, 5:15 am, Heiko Wundram <modeln...@mode lnine.orgwrote:
                              >>
                              >>I can't dig up a simple example from code I wrote quickly, but because of the
                              >>fact that explicit comparisons always hamper polymorphism
                              >I'm not going to take your word for it. Do you have code that
                              >demonstrates how "if x" improves polymorphism relative to simple
                              >explicit tests?
                              >
                              And, in case it wasn't obvious, the way to demonstrate that "if x"
                              improves polymorphism relative to simple explicit tests would be
                              posting an example where "if x" works but a simple explicit test
                              doesn't. So don't accuse me of changing the question on you: it's the
                              same question.
                              It's pretty elementary, and people thought just describing the issue of
                              polymorphism and duck-typing was sufficient to explain it. Since it
                              apparently isn't:

                              Let's say you come up with some kind of custom sequence class. You want
                              to act like any native sequence type (list, tuple, array, string, etc.)
                              in all reasonable ways (length testing, iteration, indexing, etc.) so
                              that it can be used in place of these things in code that doesn't
                              require explicit types. You know, standard polymorphism and duck-typing.

                              So you want a test for whether your custom sequence isn't empty. To
                              create an "simple, explicit test" would be defined an `isntEmpty` method
                              that you can call, like so:

                              if myObject.isntEm pty():
                              # then do something

                              However, this wouldn't be polymorphic since now someone would have to
                              call a "simple, explicit test" that doesn't exist on all the other
                              sequence-like objects. Therefore, you've broken polymorphism.

                              The solution is to override the `__nonzero__` method so that you can use
                              Boolean testing, just like all the other sequence-like objects:

                              if myObject:
                              # then do the same thing

                              Now people who use your custom sequence type don't have to write special
                              code, and code written to deal with sequences using duck typing (which
                              is typically nearly all Python code) don't have to know anything special
                              about your custom sequence class.

                              --
                              Erik Max Francis && max@alcyone.com && http://www.alcyone.com/max/
                              San Jose, CA, USA && 37 18 N 121 57 W && AIM, Y!M erikmaxfrancis
                              Everything's gonna be all right / Everything's gonna be okay
                              -- Sweetbox

                              Comment

                              • Matthew Woodcraft

                                Re: Boolean tests [was Re: Attack a sacred Python Cow]

                                Steven D'Aprano <steven@REMOVE. THIS.cybersourc e.com.auwrote:
                                "if x" is completely type agnostic. You can pass an object of any type to
                                it, and it will work. (Excluding objects with buggy methods, naturally.)
                                There are many circumstances where if a parameter is None I'd rather
                                get an exception than have the code carry on with the 'empty container'
                                branch (and silently give me a meaningless result).

                                -M-

                                Comment

                                Working...