why () is () and [] is [] work in other way?
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Thu Apr 26 05:10:07 EDT 2012
On Wed, 25 Apr 2012 20:50:21 -0700, Adam Skutt wrote:
> On Apr 25, 8:01 pm, Steven D'Aprano <steve
> +comp.lang.pyt... at pearwood.info> wrote:
>> On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:
>> > Though, maybe it's better to use a different keyword than 'is'
>> > though, due to the plain English
>> > connotations of the term; I like 'sameobj' personally, for whatever
>> > little it matters. Really, I think taking away the 'is' operator
>> > altogether is better, so the only way to test identity is:
>> > id(x) == id(y)
>>
>> Four reasons why that's a bad idea:
>>
>> 1) The "is" operator is fast, because it can be implemented directly by
>> the interpreter as a simple pointer comparison (or equivalent). The
>> id() idiom is slow, because it involves two global lookups and an
>> equality comparison. Inside a tight loop, that can make a big
>> difference in speed.
>
> The runtime can optimize the two operations to be equivalent, since they
> are logically equivalent operations. If you removed 'is', there's
> little reason to believe it would do otherwise.
I'm afraid you are mistaken there. *By design*, Python allows shadowing
and monkey-patching of built-ins. (Although not quite to the same degree
as Ruby, and thank goodness!)
Given the language semantics of Python, "id(a) == id(b)" is NOT
equivalent to "a is b" since the built-in id() function can be shadowed
by some other function at runtime, but the "is" operator cannot be.
An extremely clever optimizing implementation like PyPy may be able to
recognise at runtime that the built-in id() is being called, but that
doesn't change the fact that PyPy MUST support this code in order to
claim to be a Python compiler:
id = lambda x: 999
id(None) == id("spam") # returns True
If your runtime doesn't allow that, it isn't Python.
>> 2) The "is" operator always has the exact same semantics and cannot be
>> overridden. The id() function can be monkey-patched.
>>
>>
> I can't see how that's useful at all. Identity is a fundamental
> property of an object; hence retrieval of it must be a language
> operation. The fact Python chooses to do otherwise is unfortunate, but
> also irrelevant to my position.
It's useful for the same reason that shadowing any other builtin is
useful. id() isn't special enough to complicate the simple, and
effective, execution model just to satisfy philosophers.
>> 3) The "is" idiom semantics is direct: "a is b" directly tests the
>> thing you want to test, namely whether a is b. The id() idiom is
>> indirect: "id(a) == id(b)" only indirectly tests whether a is b.
>
> The two expressions are logically equivalent, so I don't see how this
> matters, nor how it is true.
They are not *logically* equivalent. First you have to define what you
mean by identity, then you have to define what you mean by an ID, and
then you have to decide whether or not to enforce the rule that identity
and IDs are 1:1 or not, and if so, under what circumstances. My library
card ID may, by coincidence, match your drivers licence ID. Doesn't mean
we're the same person. Entities may share identities, or may have many
identities. The Borg design pattern, for example, would be an excellent
candidate for ID:identity being treated as many-to-one.
Even if you decide that treating IDs as 1:1 is the only thing that makes
sense in your philosophy, in practice that does not hold for Python. IDs
may be reused by Python. There are circumstances where different objects
get the same ID. Hence, comparing IDs is not equivalent to identity
testing.
But I was actually referring to something more fundamental than that. The
statement "a is b" is a *direct* statement of identity. "John is my
father." "id(a) == id(b)" is *indirect*: "The only child of John's
grandfather is the parent of the mother-in-law of my sister-in-law" sort
of thing. (Excuse me if I got the relationships mixed up.)
>> 4) The id() idiom already breaks if you replace names a, b with
>> expressions:
>>
>> >>> id([1,2]) == id([3,4])
>> True
>
> It's not broken at all.
It is broken in the sense that "id(a) == id(b)" is to be treated as
equivalent to "a is b". The above example demonstrates that you CANNOT
treat them as equivalent.
[...]
> The other solution is to do what Java and C# do: banish id() entirely
Solution to *what problem*?
I do not believe that there is a problem here that needs to be solved.
Both id() and "is" are perfectly fine for what they do.
>> But that's absolutely wrong. id(x) returns an ID, not an address. It
>> just
>> happens that, as an accident of implementation, the CPython interpreter
>> uses the object address as an ID, because objects can't move. That's
>> not the case for all implementations. In Jython, objects can move and
>> the address is not static, and so IDs are assigned on demand starting
>> with 1:
>>
>> steve at runes:~$ jython
>> Jython 2.5.1+ (Release_2_5_1, Aug 4 2010, 07:18:19) [OpenJDK Client VM
>> (Sun Microsystems Inc.)] on java1.6.0_18 Type "help", "copyright",
>> "credits" or "license" for more information.>>> id(42) 1
>> >>> id("Hello World!")
>> 2
>> >>> id(None)
>>
>> 3
>>
>>
> An address is an identifier: a number that I can use to access a
> value[1].
Then by your own definition, Python's id() does not return an address,
since you cannot use it to access a value.
--
Steven
More information about the Python-list
mailing list