On Fri, 28 Feb 2014 14:25:54 +0200, Marko Rauhamaa wrote: > Chris Angelico <ros...@gmail.com>: > >> On Fri, Feb 28, 2014 at 10:30 PM, Marko Rauhamaa <ma...@pacujo.net> >> wrote: >>> Chris Angelico <ros...@gmail.com>: >>> a.state = a.INIT >> >> In theory, yes. If that's all people will ever do, then you can safely >> use == to check. Why are you using is? > > The main reason to use "is" is to indicate that the object is a sentinel > object whose identity is what is meaningful, not the content. Using == > would work but would give some poor soul the idea that the state > variable could hold any imaginable string.
Why should identity be important for testing the state of a state variable? There is a good reason for using "is" with actual sentinel values, because we wish to protect against the (rare) situation where some other object happens to compare equal to our sentinel. But why should states be treated as sentinels instead of ordinary values where identity is not important? The most important reason to *not* use "is" is that doing so *implicitly* exposes an implementation detail, namely that each state is a singleton. Identity shouldn't be that important. Why does it matter that there is only a single instance of the state INIT (say)? Why shouldn't an implementation feel free to create and discard as many instances as needed? Whether there is one INIT instance or a million is an implementation detail that shouldn't matter to the user, they should be able to just write "if state == INIT" and get the right answer. > The implementation should be able to change the state objects to any > (distinct) objects at all (say, the new enums, or ints, or some more > elaborate class instances) without any changes in the code. In practice, this is often not true. Often you have compatibility requirements with (say) external libraries or protocols, where the states are set by value. E.g. you may have to be compatible with a C library where the states are given as ints. But more importantly, you don't actually have that much freedom to change the states. Common sense[1] tells us that we're not really free to replace states with arbitrary objects, they should be values that match the name of the state. Given a state BLUE, we want inspecting it in a debugger, or printing it, to display BLUE, not sBxvGe74sk or 23 or <object object at 0xb7c1a568> and certainly not YELLOW. After all, the states are *symbols*, which means they don't really have any (internal) state or behaviour apart from their name. (In Python, we have to given them a value, we can't just refer to name BLUE without giving it a value, but the value isn't important. What we really care about is the name. Fundamentally, there's not terribly much difference between an API that says: "The colour variable can be BLUE or YELLOW" versus one that says: "The colour variable can be 'BLUE' or 'YELLOW'" In both cases, you can't change the public API. Adding or subtracting a couple of quotation marks is not a big deal (although perhaps it is a small deal). Although it may seem at first that by exposing the implementation ("states are given by strings") you're limiting your freedom to change the implementation, in practice you don't actually have that much freedom to do so, and very likely you're never[2] going to use that freedom anyway. States are symbols, and rarely need behaviour apart from equality, so why would you bother to change the implementation? (If this sounds like a mild argument against Enums, I guess it is. After all, Python worked quite well for 20+ years without Enums. Using strings as "poor man's enums" works well enough. That's why it took so long for Python to get "proper" enums, and even then, they aren't a core feature of the language.) [1] Common sense: so rare it is practically a super power. [2] Well, hardly ever. -- Steven -- https://mail.python.org/mailman/listinfo/python-list