sameness/identity

Greg Weeks weeks at vitus.scs.agilent.com
Sun Sep 30 14:54:50 EDT 2001


I said in an earlier note that I didn't want to get into the whole issue of
"sameness" and how Python "got it wrong".  Well, I changed my mind.  I'll
first admit that "got it wrong" is a poor choice of words.  Allow me to
explain what I meant.

Consider:

    x = 6.02
    y = 6.02

Are x and y identical?  They are identical as *numbers* (which I'll call
conceptual identity) but not as Python *implentations* of numbers (since
id(x) != id(y)).  Good programming style requires us to think of numbers
primarily as numbers and not as their implementations.  So we are more
interested in conceptual identity than in implementation identity.

Now consider a simple Bank_account class:

    class Bank_account:
	def __init__(me, initial_balance):
	    me.balance = initial_balance
	def deposit(me, amount):
	    me.balance += amount
	def withdraw(me, amount):
	    me.balance -= amount
	def get_balance(me):
	    return  me.balance

    my_bank_account = Bank_account(100)
    your_bank_account = Bank_account(100)

Are the two bank accounts the same bank account?  No.  (How would you feel,
for example, if I withdrew money from your bank account?)  x and y are
conceptually the same, but my_bank_account and your_bank_account are not.

Why is (conceptual) identity of numbers different from (conceptual)
identity of bank accounts?  Because bank accounts are mutable.  A bank
account can have different states at different times.  A number can't.

So, we've encountered three kinds of identity in this discussion:

    A.  conceptual identity
    B.  implementation identity
    C.  state identity

In Python, B corresponds to "is".  And to many Python programmers, C
corresponds to "==".  But that leaves A without an operator.  I'm unable to
swallow that.  So, I use "==" for A; I never use "is"; and if I need C --
which hasn't happened yet -- I write a method for it.

This works pretty well.  It works for all the immutable types.  It also
works for bank accounts *as defined above*.  That's why you won't find me
adding __cmp__ and __hash__ methods to bank accounts.  Note, by the way,
that the above bank accounts are suitable hash table keys (and I have found
that useful on occasion).

Unfortunately, "==" does not represent conceptual identity for lists and
dictionaries.  (Lists and dictionaries are like bank accounts.  They are
not conceptually identical even if they happen to have the same state.)
That's what I mean when I say Python "got it wrong".

I can't *prove* that it is wrong.  I *prefer* an operator for conceptual
identity.  And I have a *hunch* that programs are better with an operator
for conceptual identity.  But -- as all of you know -- 95% of my hunch is
really just my preference.


Greg



More information about the Python-list mailing list