Can global variable be passed into Python function?
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Fri Feb 28 19:22:51 EST 2014
On Fri, 28 Feb 2014 14:25:54 +0200, Marko Rauhamaa wrote:
> Chris Angelico <rosuav at gmail.com>:
>
>> On Fri, Feb 28, 2014 at 10:30 PM, Marko Rauhamaa <marko at pacujo.net>
>> wrote:
>>> Chris Angelico <rosuav at 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
More information about the Python-list
mailing list