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? > > Carl Banks
I think "if x" works in some cases, but not in others. Here's an example I just made up and a counterexample from my own code. Example: Here's a function, print_members. It's just something that takes some iterable and prints its members in XML. It's special-cased so that an empty iterable gets an empty tag. (This is a bit of a trivial example, I admit; the point is that the empty iterable is a special case.) def print_members(iterable): if not iterable: print '<members />' return print '<members>' for item in iterable: print '<item>%s</item>' % item print '</members>' >>> print_members(['a', 'b', 'c']) <members> <item>a</item> <item>b</item> <item>c</item> </members> >>> print_members([]) <members /> I could have used "if len(iterable) == 0:" for these cases, but only because the length of a list means something. Say I were to implement a matrix class. The length of a matrix isn't well-defined, so I won't implement __len__. I will, however, implement __nonzero__, since if it has no members, it's empty. class SimpleMatrix(object): def __init__(self, *rows): self.rows = rows def __nonzero__(self): for row in self.rows: if row: return True return False def __iter__(self): return iter(sum(self.rows, [])) >>> a = SimpleMatrix([1, 2, 3], [4, 5, 6]) >>> print_members(a) <members> <item>1</item> <item>2</item> <item>3</item> <item>4</item> <item>5</item> <item>6</item> </members> >>> b = SimpleMatrix([],[],[]) >>> len(b) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: object of type 'SimpleMatrix' has no len() >>> print_members(b) <members /> So print_members can work on iterables that have no len(), and handle the special case of an empty iterable, as long as __nonzero__ is implemented. Counterexample: While "if x" works well in some circumstances, I don't like using it for purely numeric types. For instance, I have a mutable Signal class for doing some basic DSP. Among other things, I can apply a DC offset to the signal (it just adds the offset to all the samples). I have a special case for an offset of 0 so I don't have to loop through all the samples (I also have a two-pass remove_offset method that subtracts the average; if it's already properly centred, I can skip a step). class Signal: [...] def dc_offset(self, amount): if amount == 0: return self.samples = [sample + amount for sample in self.samples] Here, "if amount == 0" is deliberate. At no point should I be adding an offset that's a list or a dict, even an empty one. Signal.dc_offset should raise an exception if I try to do that, because that indicates there's a bug somewhere. If I do pass in [] or {}, that test will fail, and it will try to add the list or dict to the samples, at which point I get a TypeError. Geoff G-T -- http://mail.python.org/mailman/listinfo/python-list