Jason Tackaberry wrote: > On Fri, 2008-03-14 at 21:44 +0100, Duncan Webb wrote: >> :-) typical evolution of software, started off testing a few methods and >> then added more and copied the code for the next function and changed >> bits, then changed the function again; over time they all ended up >> looking very similar. > > I'm pretty sensitive about this when writing my own code. As soon as I > find I'm repeating myself, I look to abstract it. But I'm also > sometimes overcome by my own laziness. In kaa, we're starting to see > this idiom a lot: > > tp, exc, tb = sys.exc_info() > raise tp, exc, tb > > It's only 2 lines, but it's sort of cumbersome, not exactly obvious, and > it's repeated enough that a well named function really improves > readability. > > def reraise(): > tb, exc, tb = sys.exc_info() > raise tp, exc, tb
I know that this is a very easy trap to fall into, especially when concentrating on getting something else to work and you've done a lot of changes. >> if len(args) == 1: >> result = rc.findMatchesNow(args[0]) >> elif len(args) == 2: >> result = rc.findMatchesNow(args[0], args[1]) >> else: >> result = rc.findMatchesNow() >> >> What if the cleanest way of writing a function to call the function with >> different arguments, a decorator may work nicely but the may be a really >> simple way. > > The cleanest way of writing the above is: > > result = rc.findMatchesNow(*args) > > Now, if findMatchesNow() cannot take more than 2 arguments (which I > suspect is so, and this is fine), then if the args tuple contains > 3 > elements, this will cause an exception. And this likely fine too. This is exactly what I wanted to achieve, even though I knew about the *args and **kwargs and what they do. > In general, prefixing a sequence with '*' and/or a dictionary with '**' > can be used to apply the sequence as arguments and/or the dictionary as > keyword arguments to the given function. See > http://docs.python.org/ref/calls.html for specification. > > >> The second question arises from the last test case, it doesn't seem as >> simple and clean as it could be, is there a simpler solution? > > I'm not sure how that differs from your first question, but I suspect I > answered it above. (If not, please elaborate.) The questions were related, the first was how to factor out the common code and the second was how to pass the command line arguments to the test calls. Both really boil down to using the * operator. > In terms of the boilerplate I suggested you move into a separate > function, I would do it like this: > > def _rpc_wait(self, rpc, *args): > ip = self.recordserver_rpc(rpc, *args) > if ip is None: > return None > # wait() already does get_result() for you. Note that it can > # raise an exception if the remote end raised an exception. > result = ip.wait() > _debug('%s.result=%r' % (rpc, result), 1) > return result > > Then for example the code that I quoted in my previous email could be > replaced with: > > return self._rpc_wait('findNextProgram', isrecording) > > And similarly for the other 16 occurrences. All arguments after the rpc > name are optional, and they are passed as-is to self.recordserver_rpc. > > > HTH, It does a lot, you can do some surprising things in Python that you can't do in other languages and still keep the code clean. The more I use Python the more I appreciate the genius of its design. As you will have noticed from the svn log I've done as you suggested, it works great. A big thank you Duncan ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ Freevo-devel mailing list Freevo-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/freevo-devel