Can Python function return multiple data?

BartC bc at freeuk.com
Thu Jun 4 20:16:23 EDT 2015


On 05/06/2015 00:13, Steven D'Aprano wrote:
> On Fri, 5 Jun 2015 06:52 am, BartC wrote:
>
>> On 04/06/2015 18:11, Steven D'Aprano wrote:
>>
>>> If there is
>>> any language where assignment uses one style and argument passing always
>>> uses another, I've never come across it.
>>
>> My language does that. I'd be very surprised if it was the only one in
>> existence that does so.
>
> I would be. That means that
>
> func(x)
>
> and
>
> tmp = x
> func(tmp)
>
> behave differently,

Not as far as func() is concerned. But overall there is a difference 
because now tmp contains a copy of x. (Also, if x contains a list for 
example, func() can modify the copy in tmp, not in x. But this shouldn't 
be surprised because the code is different!)

  and that would be very surprising to me (and, I think,
> most people).
>
>> Assignments involve a deep copy. Argument passing is something
>> in-between by-value and by-reference (depending also on the type of data
>> involved).
>
> When you say "something in-between ...", do you mean pass by sharing?

No, it's a rather untidy mechanism which is not intended to be used when 
a parameter is modified (mutated), because the information passed is 
incomplete. But for read-access, or local assignment is used within the 
function, it works as expected.


>> There is a also an actual by-reference mode (where a pointer
>> is passed).
>
> Passing a pointer is not necessarily by reference. Pass by sharing also uses
> a pointer.

This can get tricky to explain. If variables (if you forgive me that 
term) are implemented actually as pointers, then when you pass that 
variable to a function, a copy of the pointer it contains is pushed (I 
think this is how CPython works).

In that case, it is not passed by reference, even though a pointer is 
used. Because the pointer doesn't point /at/ the variable, but with it. 
So if the variable contains a List, its pointer points to the list, and 
the function parameter points at the same list; it can change the list, 
but it can't make the variable point to something else.

When I use pass-by-reference then, regardless of whether variables 
already make use of pointers, I need to construct an extra pointer that 
points /at/ the variable (and box it in my case).

(Example of how I think CPython works:

  def fn():
     a = 5622
     b = [10,20,30]

For this purpose, a and b are locals, and they are allocated on some 
sort of stack, which gives them one pointer each. After those 
assignments, they might contain:

   a (pointer 1003)  ->    1003: [int 5622 ....]
   b (pointer 1007)  ->    1007: [list ........]

Now the following is executed:

     fn2(a)

A copy of a, (pointer 1003), is pushed, which points to the int. These 
are immutable anyway. It is impossible (AFAIK) to make a contain 
something else, such as a string, from outside fn().

The language could be extended:

     x = &a

x might now be:

   x (pointer 1012)  ->    1012: [Ref (pointer 1003)]

Now it is possible to call fn2(x), and inside fn2, some dereferencing is 
done (using explicit pointer ops, C-style):

      *x = "XYZ"        # this will change a)

-- 
Bartc



More information about the Python-list mailing list