About the implementation of del in Python 3

Steve D'Aprano steve+python at pearwood.info
Thu Jul 6 14:12:58 EDT 2017


On Fri, 7 Jul 2017 01:21 am, Marko Rauhamaa wrote:

> Steve D'Aprano <steve+python at pearwood.info>:
> 
>> On Thu, 6 Jul 2017 07:24 pm, Marko Rauhamaa wrote:
>>
>>> While talking about addresses might or might not be constructive, let
>>> me just point out that there is no outwardly visible distinction
>>> between "address" or "identity".
>>
>> Er, yes there is. Address refers to a position in space. Identity
>> refers to the state or quality of being identical (i.e. the same). My
>> identity remains the same as I travel from one address to another.
> 
> That sounds metaphysical.

A concrete example of a person moving from one address to another is about as
far from metaphysical as it is possible to get.

You've done this repeatedly over the years, insisting that Python needs a formal
definition of identity and claiming that the definitions given are circular,
based on what seems to me to be metaphysical and vague criticisms.

In practice, none of your questions about identity seem to make the slightest
bit of difference to Python programming. The Python concept of identity, as
informal as it might be, works, and leads to a consistent and understandable
programming model.

I still don't understand what you get out of this. Will it make you a better
programmer? No. Will it help you understand Python code better? No. Will it
help you predict the result of calling the `is` operator? No, you seem to be
perfectly able to correctly predict the result when required.

So apart from the chance that you're just trolling us for fun, I don't
understand what possible motive you have or why you think this is an important
question.

But on the possibility that you are genuinely interested in the answers, I'll
try to answer your questions below.



> What I'm looking for is snippets of Python code that illustrate the
> difference.

The difference between *what*?

Your statement here is too vague for me to understand, but I'll take a guess:
you want some code demonstrating the difference between address and identity.

Well, for starters, that's a category error: address and identity are not the
same kind of thing, and so cannot be compared directly.

An address is a concrete location or place, in other words a physical position
in some space, while identity is the abstract state or quality of being
identical (sameness), in other words a state of being.

In full generality, I doubt that there is any definition of "identity" which can
be fully satisfactory, but in the context of Python we can be more specific:

Nominally two objects are identical (have the same identity) if they are one and
the same object, and are not identical if they are different objects.

Python doesn't provide any functions for getting the address of objects, in fact
the Python execution model doesn't have a concept of an object's physical
location. But we can model location by considering the index of an object in a
list or array as a kind of address:

a = [1, 2, None]
b = [1, 2, 3, 4, 5, 6, 7, 8, None]
# Address of None, within a
assert a.find(None) == 2
# Address of None, within b
assert b.find(None) == 8

# Are these two references to None references to the same object?
assert a[2] is b[8]


There is no function or operator or statement in Python that returns the
identity of an object. Such a thing cannot exist: identity refers to a state of
being, like "hot" or "cold" or "dead" or "alive", it is not in and of itself a
value that can be returned any more than I can hold "alive" in my hand. It is
an abstractum (an abstract thing):

https://en.wikipedia.org/wiki/Abstract_and_concrete

Treating identity as a thing itself is an example of the fallacy of reification:

https://en.wikipedia.org/wiki/Reification_%28fallacy%29

Hence:

Abstract: identity (of a certain thing, e.g. the identity of a person)

Concrete: a specific thing (e.g. a specific person)

And in the context of Python:

Abstract: object identity

Concrete: this particular object

What Python does provide is a function to compare (nominally) two values and
return True if they refer to the same object in the Python virtual machine,
otherwise return False. Namely the `is` operator.

Abstract: do the two operands have the same identity?

Concrete: are the two operands the same object?


(Note that the Python VM is an abstraction which is emulated by the interpreter.
The Python VM operates in terms of objects, but the interpreter may be written
in a language without objects. Fundamentally computers do nothing but flip
bits, so it is abstractions all the way down. And even flipping bits is an
abstraction.)

Python also provides a function "id()" which returns a ID number that uniquely
distinguishes the object from any other object, providing the two exist at the
same time. The ID number is not the same thing as the object itself, nor is it
the "identity" of the object. It's just a label for the object, one which can
cease to be valid once the object ceases to exist.

You are not your social security number, or tax number, or your membership
number at the local branch of the Loyal Order of Water Buffalo Lodge. They are
just labels that represent you in a compact form.


> That's how you can illustrate the difference between the "==" and "is"
> operators:
> 
>     >>> ["a"] is ["a"]
>     False
>     >>> ["a"] == ["a"]
>     True
> 
>> Those are good ID numbers.
>>
>>>    fermionic quantum state
>>
>> I don't think that is, since two electrons (fermions) in different
>> atoms can be in the same state.
> 
> Beside the topic but (unlike the bosons) every fermion in the universe
> differs in at least one parameter from all the rest. In your case, they
> belong to different atoms.

"The atom you are bound to" is not a quantum state. That's more like location, I
guess. The prohibition of fermions being in the same state implies "at the same
time, in the same place".

In any case, I see your point, and quibbling about fermion state isn't really
shedding light on anything.


>>> Ignoring the word that is used to talk about object identity, it would
>>> be nice to have a precise formal definition for it. For example, I know
>>> that any sound implementation of Python would guarantee:
>>> 
>>>     >>> def f(a): return a
>>>     ...
>>>     >>> a = object()
>>>     >>> a is f(a)
>>>     True
>>> 
>>> But how do I know it?
>>
>> Which part is unclear? The fact that f(a) returns a, or the fact that
>> `a is a` is true?
> 
> In fact,
> 
>     a is a
> 
> would be a *great* start for a formal definition/requirement of the "is"
> operator, although you'd have to generalize it to
> 
>     b is b
>     c is c
> 
> etc as well.

Why do you have to generalise it? The name "a" here stands in for any reference
to any object. If I give you the mathematical equation:

2x + 3x = 5x

you should understand that it holds true for any x. I don't have to generalise
it to:

2y + 3y = 5y

2z + 3z = 5z

2a + 3a = 5a

2b + 3b = 5b

etc.


> Unfortunately, when I try it, I get: 
> 
>     >>> a is a
>     Traceback (most recent call last):
>       File "<stdin>", line 1, in <module>
>     NameError: name 'a' is not defined

Now you're just trolling.

If "a" is not defined, of course it isn't identical to itself, since it doesn't
exist. If there's no actual object, there's nothing to be identical.

"The fourth side of this triangle is longer than the hypotenuse" is likewise a
error. Triangles don't have four sides, the fourth side does not exist, and it
is nonsensical to describe it as either longer or shorter than the hypotenuse.

Binary valued logic has difficulty with statements such as these, so-called 
"vacuous truths". Sometimes it is better to just raise an exception, as Python
does, or take a third option:

Question: Is the fourth side of this triangle longer than the hypotenuse?

Answer: Mu.

https://en.wikipedia.org/wiki/Mu_%28negative%29



> Actually, getting the wording right in these kinds of definitions is
> surprisingly tricky.
> 
>> First part is implied by Python's execution model,
> 
> [Citation needed]

Good question!

I thought this was covered in the execution model page of the docs:

https://docs.python.org/3/reference/executionmodel.html

but I was wrong, it doesn't seem to describe the semantics being described. Nor
does the section on function call semantics:

https://docs.python.org/3/reference/expressions.html#calls

although it comes close:

"Otherwise, the value of the argument is placed in the slot"

Unfortunately that's insufficient. The FAQs add a little more information:

https://docs.python.org/2/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference

I think, unless I've missed something, that the current documentation doesn't
define the way arguments are bound to function formal parameters.

I know what the answer is: parameters are passed using the same semantics as
CLU, namely what Barbara Liskov named "pass by sharing" or "pass by object
sharing". Python luminary Fredrik Luhn (the Effbot) prefers the term "pass by
object" or "call by object":

http://effbot.org/zone/call-by-object.htm


Here's the function call again:

>>>     >>> def f(a): return a
>>>     ...
>>>     >>> a = object()
>>>     >>> a is f(a)
>>>     True


Let's follow the steps taken by the interpreter:

(1) The function "f" is defined and bound to the name "f".

(2) A value of type "object" is instantiated, and bound to the name "a".

(3) The name "a" is looked up, returning that same object instantiated 
    in step 2 above. Call this "the left hand operand".

(4) The name "f" is looked up, returning the function object defined
    in step 1. Call this "function f".

(5) The name "a" is looked up again, returning the same object instantiated
    in step 2 above. Call this "the function argument".

(6) The function f is called with the function argument as its argument.

(7) The function argument is bound to the function f's formal parameter "a",
    creating a local variable in the function f's namespace.

[Note: this example would have been less confusing if the parameter "a" was
given a name different from the outer variable "a". The two "a"'s are different
variables.]

(8) The function f looks up the local variable "a" (which is the formal
    parameter "a", defined in the parameter list), which is currently
    bound to the object instantiated in step 2 above, and returns that
    object. Call this "the right hand operand".

(9) Finally the `is` operator compares the left hand operator to the
    right hand operator, sees that they are the same object, and
    returns True.


Unfortunately I don't think this is officially documented as such, or at least I
haven't found it, so the "documentation" is the reference implementation,
namely the CPython interpreter.

Documentation patches are welcome.


>> and the second by the definition of the `is` operator.
> 
> [Citation needed]

Now you're taking the piss. Do I have to look everything up for you?

https://docs.python.org/3/reference/expressions.html#is

"x is y is true if and only if x and y are the same object."



>> I'm genuinely unsure what part of this you think needs a precise
>> formal definition.
>>
>> (That's even putting aside that it may not be possible to give a
>> precise formal definition of "identity". See, for example, "The Axe of
>> my Grandfather" paradox.)
> 
> There are many ways to define identity:
> 
>  1. Map Python's data model to that of another programming language, for
>     example C. This technique is very common and useful. No wonder the
>     word "address" keeps popping up.

That doesn't define identity.

It also has the flaw that Python the language is independent of any specific
implementation written in a particular language. For instance, in CPython,
objects have a consistent and stable memory location during their lifetime, but
that is not the case for Jython, IronPython or PyPy.



>  2. List a number of formal requirements: any implementation that
>     complies with the requirements is a valid implementation of the
>     language.

You forgot the most practical way:

3. Follow the example of the reference implementation.




-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list