Can Python function return multiple data?

Steven D'Aprano steve at pearwood.info
Fri Jun 5 07:06:22 EDT 2015


On Fri, 5 Jun 2015 01:16 pm, Rustom Mody wrote:

> Consider the C canonical linked-list example (of some type T):
> 
> struct node
> {
>    T elem;
>    struct node *next;
> };
> 
> Is the list in C to be identified with 'struct node'?

Lists in C are not first class values. There is no one thing which can be
identified as the entire list, because the C language gives you the tools
to break any "list" abstraction.

In C, there is no single thing which refers to the entire list, *except by
convention*. There is *at least* one node which represents the head of the
list, followed by other nodes:


node->node->node->node->node
             ^
             |
node->node---

(ASCII diagram best viewed in a monospaced font)

But there is nothing which encapsulates the entire list, and indeed the
concept "the list" is ill-defined, as in the above diagram. We can use the
convention that "the list" means "the sequence of nodes, starting from this
node, which we assume is the head of the list", but that's about it. You
might even find some clever way of tracking which node is the head and
which are not in your own code, but C won't do it for you. You might refuse
to create such double-headed lists as shown above, but C won't enforce that
rule for you, you have to enforce it yourself. In short, C doesn't have the
concept of lists as first class values and so anything you do with it is
entirely in your own hands.


[...]
> My conclusion: C does not support lists at all in a first class way.

Exactly!


> The same situation obtains here in python:

Not so.

In Python, lists *are* first class values, and the Python language manages
all the book-keeping for you to ensure that when you look at a list, it is
the whole list, regardless of implementation. From your Python code, you
don't have to do any book-keeping, you don't have to be careful not to
create double-headed lists, or accidentally start in the middle of the
list, since Python simply doesn't allow you to do so from pure Python code,
unlike C. So in Python, we can always consider the list as a encapsulated
whole, regardless of how it is implemented.

(CPython documents that lists are actually arrays of pointers to objects,
but that's an implementation detail we can ignore.)


> The abstract platonic immutable list is non-existent in python

Just pretend that "immutable list" is spelled "tuple".


> Use no mutation and the pretence that the list [1,2] *is* the list [1,2]
> works.
> 
> Start using mutation and the ground starts wobbling.

Mutation is irrelevant here. Some objects are immutable, others are mutable,
but the language semantics are the same for both.

In particular, Python provides as a language feature two ways to compare
objects for identity. Python makes no promises as to when it will re-use
immutable objects, but it does promise that you can always test for re-use
by using `is` or `id()`. So there's no "wobbly ground" here. You can
*always* tell if (supposedly) two objects are in fact the same object or
not, since `is` cannot be shadowed or monkey-patched.


> The only way to stay steady (that I know) in this wobbly world is to hold
> to two concepts:
> 1. The abstract platonic immutable type -- good to think with, supported
> by python in only a half-assed way
> 
> 2. The 'maybe-reference-maybe-value' actual mess
> 
> And to keep dancing between these

All the words are in English, but I have no idea what you are trying to say
here.


-- 
Steven




More information about the Python-list mailing list