On Mon, 16 Jul 2012 20:57:43 -0500, Andrew Berg wrote: > I have a better real example, but I opted not to use it before since it > requires some explanation - IRC messages. A client-to-server message has > the basic form of b'COMMAND arguments :message' (e.g. b'PRIVMSG #channel > :hi guys!'). Some commands have no message part because there is no > message associated with it (e.g. b'JOIN #channel') and there is at least > one where there is a big difference between a blank message (b'') and no > message - b'TOPIC #channel' is a request for the topic while b'TOPIC > #channel :' clears the topic since the part after the b':' is b'' > (b'TOPIC #channel :Welcome to #channel' sets the topic to "Welcome to > #channel").
Okay, so you have two distinct "nothing" states when considering the message part of an IRC command: the empty string, and missing. That's okay. Floats have two zeroes (+0.0 and -0.0); complex numbers have four. (Although they try hard to hide that distinction from you.) There's nothing that says that you can only have a single falsey value in a type, or that you might not sometimes wish to distinguish between different false-like states. You need to distinguish between the many different true-like messages, so you should not be surprised that you need to distinguish between two false-like messages. There are many ways to implement this. Here are just the most obvious: 1) a Command object where the message attribute is optional, but if present, it is always a string; 2) a Command object where the message attribute is always present, but can be a string or some non-string sentinel value (e.g. None); 3) a string, where the message attribute is determined by the location of the colon, if any 4) a tuple with either two or three fields: (command, channel [,message]) > In my code, I would have an object representing a message > rather than parsing it multiple times. If the message > attribute is not None, I send b'{command} {args} :{message}', otherwise > b'{command} {args}'. Clear and obvious. Nothing wrong with that. > I could do: > > if has_message: > send('{command} {args} :{message}') > else: > send('{command} {args}') > > but then I'd have to make sure has_message stays accurate since message > won't necessarily be. Yes, keeping a separate variable is a mug's game. Encapsulate it in the Command object, and have the Command object responsible for keeping it in sync (assuming it is mutable), or just make Command immutable and be done with it. > Or maybe I could leave message undefined and catch > the appropriate exception. However, using None is the cleanest and most > obvious. Yes it is. What's your point? You've discovered a real-world situation where you can't collapse the entire universe of valid values into just two, True and False, without losing information. Did you think that this would be surprising? Python developers often talk about interpreting objects "in a boolean context" -- that's a pretty big hint that the semantics are to collapse the value into two states. If you need three (or four, or fifty) distinguishable states, then obviously boolean context will not solve your problem. I never said it would. -- Steven -- http://mail.python.org/mailman/listinfo/python-list