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

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Wed Nov 19 07:50:45 CET 2008


En Wed, 19 Nov 2008 01:14:28 -0200, <rurpy at yahoo.com> escribió:
> On Nov 18, 10:22 am, Steve Holden <st... at holdenweb.com> wrote
> in thread "Python-URL! weekly Python news and links (Nov 17)":
>> rurpy at yahoo.com wrote:
>> [...]
>>> One of the reasons I would like to formulate a good
>>> model of an object's value and type is so that I could
>>> try to offer something better.  Responses like yours
>>> are significantly demotivating.
>>
>> And yet you argue when people try to explain to you that objects don't
>> *have* values, objects *are* values. Objects have attributes, which are
>> references to other values. One of an object's attributes is its type.
>
> I am sorry for arguing with you.  I hear you
> and others saying that the value (in the english
> language sense of value) of an object *is* the
> object.
>
> But before I address that, I am a little confused
> by what you wrote above.  Quoting the PLR again,
> "Every object has an identity, a type and a value."
> I presumed "value" to include attributes.  Are you
> saying the correct statement in the PLR should have
> been, "Every object has an identity, attributes, and
> a value"?

I'll try to avoid any confusion here. I cannot say what defines a Python  
object in a generic way, but I do know what defines a CPython object. That  
is, I can talk about the current C implementation.
In CPython, an object is a C struct: PyObject. No more, no less. Most  
functions in the CPython API receive, return, or handle PyObject pointers  
everywhere. Every object in CPython is represented as a PyObject instance,  
and has the following properties:

  - An object has *identity*: its memory address, immovable, fixed once the  
object is allocated.
  - An object has a *type*: its ob_type field (a pointer to the type  
object). The type is uniquely defined - no type inference is ever done. It  
may be changed after the object was created but only if several  
prerequisites are met.
  - An object has *state* [or value]: everything else stored in the struct.

The PyObject struct is very small and contains nothing apart from the  
ob_type field [1]. So a PyObject instance has no state, there is nothing  
more defining it. A PyObject instance just "is": it has only identity and  
type, it does not carry any state.

More useful objects are built by extending the PyObject struct at the end  
- that is, adding more and more fields. By example, a PyIntObject adds a C  
"long" field. That new field is the only difference between a PyIntObject  
and a bare PyObject. We can say that a PyIntObject gained some "state":  
the integer stored inside that field; some people would like to say "its  
value". So, to describe completely a PyIntObject, one has to tell -in  
addition to its type and identity- *which* number it contains.

More complex objects are built using the same principle: by example, a  
PyFunctionObject contains nine more fields (func_code, func_doc, etc.) in  
addition to the bare PyObject. Those additional fields represent the  
"state" of the function object, and are required to describe it completely.

Instances of user-defined classes may contain arbitrary attributes; this  
is implemented using a dictionary. We refer to this dictionary as the  
'__dict__' attribute in Python code, but it is just another field in the  
object struct, as anything else. In other words, arbitrary attributes are  
also stored (indirectly) in the object struct.

So, at least when one looks at the CPython implementation, things are  
rather simple: an object is a struct located at certain address  
(determines its identity), has a certain type (a field in the struct) and  
has a state (everything else in the struct).

You may want to say "value" instead of "state" in all the above  
description, but I think it becomes confusing later.

Expressions: Evaluating an expression yields a result, and that result is  
an *object*. One could say "the value of this expression" -- but remember  
that it is an *object*, like everything else in Python. If one says  
"objects have identity, type and value", one cannot say at the same time  
"expressions return a value" because the word "value" has a different  
meaning in both sentences.

Calling: Same problem applies to "call-by-value". If one says that objects  
*have* a value (that implies that value is *part* of the object), it  
itsn't its "value" what is passed when a function call is made. The  
*whole* object is passed, not its "value" alone. Saying "call-by-object"  
describes more accurately what actually happens.

Conclusion: To avoid any ambiguity, I'd say that "objects have identity,  
type, and state" (not value), "expressions evaluate to an object" (again,  
not value), and "Python passes arguments to functions using a  
call-by-object protocol". Given these terms, even "the value of this  
expression" might be acceptable because "value" could not be confused with  
any "part" of an object.

> Here is why I am having trouble accepting the
> explanations you and others have kindly offered
> me.  If values are objects then the words "object"
> and "value" are synonymous, yes?  Fine, I can see
> that could be a desirable thing.  Value is more
> natural than object for people coming to Python,
> for example.

"state" is more common in OO theory, I think. I'd reserve "value" to any  
informal description, and use "state" when refering to "anything the  
object carries with itself".

> I hope you see why I find the "value is object"
> to be an unacceptable explanation of Python
> objects.

Me too. I hope the above explanation helps to understand the difference.  
It is based on a specific implementation, but I feel that describing what  
CPython actually does is easier that talking about abstract concepts.  
Perhaps somebody can come with an abstract explanation based on this  
concrete examples.

[1] There is another field always present: ob_refcnt, but it should be  
considered an implementation detail of the reference counting mechanism.  
Additional fields may be present in a debug build of Python.

-- 
Gabriel Genellina




More information about the Python-list mailing list