On Jul 29, 4:08 pm, Erik Max Francis <[EMAIL PROTECTED]> wrote: > Carl Banks wrote: > > On Jul 29, 1:30 pm, Carl Banks <[EMAIL PROTECTED]> wrote: > >> On Jul 29, 5:15 am, Heiko Wundram <[EMAIL PROTECTED]> wrote: > > >>> 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.isntEmpty(): > # 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.
Bzzt. "if len(x)!=0" is a simple explicit that would work for this class and all built-in containers. (Or should--Steven D'Aprano's objections notwithstanding, any reasonable container type should support this invariant. From a language design standpoint, an "empty" builtin could have been created to simplify this even more, but since there isn't one len(x)!=0 will have to do.) Let me reframe the question to see if we can make some headway. The vast majority of true/false tests fit into one of the following four categories: 1. Testing the explicit result of a boolean operation (obviously) 2. Testing whether a numeric type is nonzero. 3. Testing whether a container type is empty. 4. Testing whether you have a (non-numeric, non-container) object of some sort, or None. There's a few other cases, but let's start with these to keep things simple and add other cases as necessary. We already know that cases 2, 3, and 4 can, individually, be converted to a simple explicit test (using x!=0, len(x)!=0, and x is not None, respectively). As long as you know which kind of object you're expecting, you can convert the implicit to an explicit test. Now, you guys keep whining "But what if you don't know what kind of object you're expecting?!!" It's a fair question, and my belief is that, in practice, this almost never happens. Duck typing happens between numeric types often, and between container types often, but almost never between both numeric and container types. Their usages are simply too different. So I present another question to you: Give me an useful, non-trivial, example of some code that where x could be either a numeric or container type. That would be the first step to finding a counterexample. (The next step would be to show that it's useful to use "if x" in such a context.) Once again, I'm invoking the contraint against simply using x in a boolean context, or passing x to a function expecting a boolean doesn't count, since in those cases x can be set to the result of the explicit test. So none of this: def nand(a,b): return not (a and b) Or anything trivial like this: def add(a,b): return a+b Carl Banks -- http://mail.python.org/mailman/listinfo/python-list