Official definition of call-by-value (Re: Finding the instance reference...)

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sun Nov 16 03:38:25 EST 2008


On Sat, 15 Nov 2008 19:41:20 -0800, rurpy wrote:

>> I prefer another definition of object: an object *is* a value, rather
>> than *has* a value. That value consists of identity, type (or class),
>> and everything else of interest which is sometimes also called "value".
>> Since identity is usually unimportant, and type is assumed from
>> context, we can often get away with stating that the "everything else
>> of interest" is *the* value.
> 
> The Python Lang. Ref. says:
>   object = identity + type + value

I believe that the language reference says that objects have an identity, 
a type and state, but I'm too lazy too look it up. I'd be happy with that 
definition.


> You are defining objects as:
>   object = identity + type + (object - (identity + type)) value = object
>   - identity = type + (object - (identity + type))
> 
> Seems to me it is easier just to give the "object - (identity + type)"
> part a name, say, "value". :-)

I would call that state. Then I would say that the value of an object is 
the object's state, possibly with the identity and/or type if they are 
important in context.


> I also question, "type is assumed from context".  To me, type is very
> objective: it is the set of methods and other attributes that define the
> behavior of the object.

Sure. But that doesn't contradict my statement that often type can be 
assumed from context, although I didn't explain myself terribly well. 
What I meant was that the range of types we accept as having the same 
value will depend on what we want to do with the values. That's duck-
typing: if we only care that a thing has webbed feet, then everything 
else about the various waterfowl is mere decoration. The only thing of 
significance is the presence or absence of webbed feet, and in principle 
we are indifferent as to whether we get Goose(3) or Duck(3) or Swan(3), 
or even Pelican(3). Other aspects of the object's behaviour (its type) 
such as whether they honk, quack, or hiss, are irrelevant.

>From a philosophical position, Goose(3) has a different value to Duck(3), 
and I have no problems with saying so. But in a practical sense, if I 
don't care what sort of web-footed thing I get, then everything else is a 
mere red stripe, an arbitrary decoration or implementation detail.


 
>> I usually talk about one of the three levels of value:
>>
>> (1) The value of the NAME (or variable) x is the object int(3); that
>> is, the thing denoted by the symbol x is the object int(3).
> 
> OK, but a name is a rather abstract concept, is it not?  

Not at all, it is a fundamental part of Python, analogous to variable.


> Because of
> Python's interpreted nature, names can't be compiled away as in C, they
> need a concrete runtime existence, but does the language definition need
> to assume that?

Of course. It wouldn't be Python if they didn't. However, remember that 
objects don't have names.


> And per innumerable previous discussions, is it not preferable to "bind
> the name to an object" sidestepping any need for "value" in this
> context?

Nevertheless, people will insist on asking "what's the value of x?" and 
expect to get the answer 3 if they have previously executed x = 3. I 
don't see that this is a problem. The name x is a symbol, and it denotes 
the object 3. Where's the problem in using the term value?


 
>> (2) The value of the OBJECT int(3) is the specific concrete
>> instantiation that makes it the thing that it is rather than another
>> thing (a complicated way of saying that the value of an object is
>> itself); that is, the thing denoted by the symbol int(3) is some
>> specific byte pattern in memory which causes that object to be int(3)
>> rather than some other object.
> 
> I don't see how saying "the value of an object is itself" is
> particularly useful.  We already have a word for what an object is, it
> is "object". :-) 

I didn't say it was very useful. As far as I'm concerned, asking what the 
value of an object is is not a useful question.



> The point of the word "value" is to describe, in a
> general way, without defining implementation details, what you describe
> as "some specific byte pattern in memory which causes that object to be
> int(3) rather than some other object" and does not mix in other
> bit-pattern differences, such as differences in type which are not
> relevant to what we intuitively think of as "value".
> 
>> To put it another way, the value of that object is whatever properties
>> of the object distinguish it from any other the whole number 1.

Sorry, that sentence is incoherent. What I meant to write was:

"To put it another way, the value of that object is whatever properties 
of the object distinguish it from anything other than the whole number 1."

 
> This is saying something different, that the value of an object depends
> on how it's type relates to some non-programming-language concept
> ("whole numbers" in this case) that the object attempts to model.

Try as we might, we can't entirely escape that objects are merely 
modeling things in the outside world, or abstract concepts. Scrub out the 
reference to "type" in your sentence, and I would agree with you: the 
value of an object depends on how it relates to the thing the object 
attempts to model.


 
>> Since
>> identity is (usually) unimportant for distinguishing one object from
>> another (we usually care whether x==y, not whether x is y) the identity
>> is not part of the value.
> 
> The result of x==y depends solely on the behavior (methods) of x.

Nonsense.

>>> class EqualsAll(object):
...     def __eq__(self, other):
...             return True
...
>>> 5 == EqualsAll()
True


The methods of 5 don't even get called. This of course is a special case, 
because 5 is a built-in, but in general, the result of x==y depends on 
*both* x and y.


> (To
> be anal, the behavior of x might be to delegate calculating the result
> to y).

No, that's not what x does. You *don't* need to do this:

class MyClass(object):
    def __eq__(self, other):
        if some_condition:
            return other.__eq__(self)

x does not delegate anything to y, unless you explicitly code it like I 
have above. It just happens, automatically performed by the Python VM.



> That behavior (if reasonable) will take into consideration the
> "value"s of x and y.  This seems to imply that "value" is something more
> specific than the totality of the x and y objects.

You're assuming that == compares values, which is often a safe 
assumption, but not always.

class Silly:
    def __eq__(self, other):
        if time.localtime()[6] == 1: return True
        return False

x = Silly()
y = 5

On Tuesdays, x==y returns True. Does that mean the value of x has changed 
at Monday 11:59:59pm and will change again at Tuesday 11:59:59pm? I don't 
think so. I think the value of x remains the same, but the behaviour 
varies from time to time. I think the value of x is "a thing which claims 
to be equal to everything on Tuesdays, and equal to nothing every other 
day".



>> We're generally indifferent to the serial number on our ten dollar
>> bills: any note is (usually) as good as any other note. But sometimes
>> identity is important, and in some specific contexts I'd be happy to
>> say that the value of a symbol must include the identity of the object.
> 
> What you or I think is important in a calculation need not have a
> bearing on an object's value.

Are you trying to say that the value of objects is independent of human 
thought? 

The CPython object int(3) happens to have the *exact* same representation 
in memory as the string "steve is a poopy-head" in some other Python 
implementation. (I can't tell you what that implementation is, but I know 
it exists in principle.) The only difference between the two is that in 
CPython that collection of bytes represents the whole number three, while 
in the other implementation, it represents a rather childish insult. The 
physical thing itself is exactly the same, but the meaning -- its value 
-- depends on the interpretation.

(Have you ever read "Godel, Escher, Bach: An Eternal Golden Braid"? I 
recommend it highly.)

If you think that is too hypothetical to take seriously:

http://www.ioccc.org/1986/applin.c

A single set of bytes which are legal and useful (well, not very useful) 
C, Fortran 77 and Bash code.



> id() does not need to consider that
> identity is part of an object's value -- its programmer needed merely
> use identity if that's what was needed, while it's argument goes on
> having whatever value it has.

This is a red-herring. id() itself does one thing and one thing only: 
return a numeric ID representing the identity of the object. The id() 
function doesn't care what the object is, only what it's identity is.


[snip] 
> Is the value of float(1.0/3.0) the same as float(.3333333333333333)? 
> Mathematics says no, but Python (at least on my machine) says yes.  (At
> least if you accept that the "==" operation is written to compare
> values.)

What you've discovered is that the abstraction "floating point numbers 
represent real numbers" sometimes fails. I don't think that has any 
baring on what the value of float(1.0/3.0) is. The value is "one third", 
or at least as close to one third as the implementation (the abstraction) 
allows.

There is nothing in the concept of value that implies that the 
correspondence between the symbol and the thing itself must be exact. 
Consider x = float(1.0/3.0). When talking about the name 'x' and the 
thing float(1.0/3.0), the correspondence is exact: x really does denote 
the float object. But when talking about the symbol float(1.0/3.0) and 
the thing it represents, the abstract real number one third, the 
correspondence is not exact: floats fall short in a number of ways.
 


[snip]
> So you would say that a and b have different values below?
> 
> class My_int(int):
>     def __init__(self): self.foo = None
> a = int(3)
> b = My_int(3)

As I explained in another post, yes, with some provisos.

 
> How can one have an objective definition of "value" if it depends on
> context?

How can you not?



-- 
Steven



More information about the Python-list mailing list