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