Python function returns:

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Michael Yanowitz

    #1

    Python function returns:

    I am still new to Python but have used it for the last 2+ months.
    One thing I'm still not used to is that functions parameters can't
    change as expected. For example in C, I can have
    status = get_network_inf o (strIpAddress, &strHostname , &nPortNumber )
    where this fictitious function returns a status, but also returns modified
    values for a hostname and a port number.
    In Python, there does not seem to be an easy way to have functions return
    multiple values except it can return a list such as:
    strHostname, nPortNumber, status = get_network_inf o (strIpAddress,
    strHostname,
    nPortNumber)
    Am I missing something obvious? Is there a better, or more standard way
    to return values from functions?

    Thanks in advance:
    Michael Yanowitz


  • Diez B. Roggisch

    #2
    Re: Python function returns:

    Michael Yanowitz wrote:
    [color=blue]
    > I am still new to Python but have used it for the last 2+ months.
    > One thing I'm still not used to is that functions parameters can't
    > change as expected. For example in C, I can have
    > status = get_network_inf o (strIpAddress, &strHostname , &nPortNumber )
    > where this fictitious function returns a status, but also returns
    > modified
    > values for a hostname and a port number.
    > In Python, there does not seem to be an easy way to have functions
    > return
    > multiple values except it can return a list such as:
    > strHostname, nPortNumber, status = get_network_inf o (strIpAddress,
    > strHostname,
    > nPortNumber)
    > Am I missing something obvious? Is there a better, or more standard way
    > to return values from functions?[/color]

    No, that exactly is the way to go. But usually one uses tuples and the
    possibility of sequence-unpacking together to reach a solution tha at least
    to my eye looks more favorable:


    def foo(a, b):
    return a*b, a+c

    a = 10
    b = 20

    a, b = foo(a, b)


    Diez

    Comment

    • Duncan Booth

      #3
      Re: Python function returns:

      Michael Yanowitz wrote:
      [color=blue]
      > In Python, there does not seem to be an easy way to have functions
      > return
      > multiple values except it can return a list such as:
      > strHostname, nPortNumber, status = get_network_inf o (strIpAddress,
      > strHostname,
      > nPortNumber)
      > Am I missing something obvious? Is there a better, or more standard
      > way
      > to return values from functions?[/color]

      The only obvious thing you are missing is that you don't pass in values
      which are only results. Duplicating the parameters and results as you have
      above would be unlikely to happen very much in practice.

      Oh, and it doesn't return a list, it actually returns a tuple but it is
      easiest just to think of your function as just returning three results.

      Returning additional results is better than rebinding parameters because it
      makes it really clear at the point of calling which variables are
      parameters and which are results.

      The other not very pythonic thing about your example is that it returns a
      status code: Python largely tends towards using exceptions rather than
      status codes, so if in C you had:

      switch ((status=get_ne twork_info(addr , &host, &port)) {
      case S_OK:
      break;
      case ERROR_1:
      ... handle error ...
      break;
      case default:
      ... handle other errors ...
      };

      In Python you would have something like:

      try:
      host, port = get_network_inf o(addr)
      except ERROR_1:
      ... handle error ...
      except:
      ... handle other errors ...

      which means you can handle the error either right next to the call or at
      some outer level (you don't have to manually propogate your status), you
      can't accidentally forget to check the status code, and the actual call is
      much simpler and clearer (especially if the error is handled at some outer
      level).

      Comment

      • bruno at modulix

        #4
        Re: Python function returns:

        Michael Yanowitz wrote:[color=blue]
        > I am still new to Python but have used it for the last 2+ months.
        > One thing I'm still not used to is that functions parameters can't
        > change as expected.
        >
        > For example in C, I can have
        > status = get_network_inf o (strIpAddress, &strHostname , &nPortNumber )[/color]

        You have to understand that Python and C are totally different beasts.

        A C variable is mostly symbolic name for a memory address, tagged with
        type infos. Assigning to a variable means storing a value at this
        address. Reading a variable means retrieving whatever value is stored at
        this memory address.

        Python does not in fact have a concept of "variables" . It has names and
        objects. A binding is the association (in a hash table) of a symbolic
        name (which is nothing more than a name) and a reference (read:
        something like a smart pointer) to an object (which is itself a complex
        data structure). So-called "assignemen t" (correct term is "binding")
        'binds' together a name and a reference to an object. Except for some
        special cases (mainly objects - which are they're own namespaces - and
        when using the 'global' statement), this creates an entry in the current
        namespace. Also, rebinding a name has no effect on other names bound to
        the same object.

        Function's params are bindings in the function's local namespace. This
        means that the params *names* are local to the function. So rebinding a
        param in a function won't have no effect on bindings in the caller's
        namespace.

        *But* - since many names can refer to the same object - *modifying* the
        object referenced by a name will, well, modify this object, so this
        modification will be visible everywhere.

        ie (dummy example):

        def appendToList(al ist, what):
        alist.append(wh at)

        mylist = []
        appendToList(my list, 42)
        print mylist

        What doesn't work as you'd expect is:

        def failsToHaveSide Effects(alist, anything):
        print "before rebinding : alist = ", alist, " - anything = ", anything
        alist = anything
        print "after rebinding: alist = ", alist

        mylist = []
        print "before function call, mylist = ", mylist
        failsToHaveSide Effects(mylist, 42)
        print "after function call, mylist = ", mylist


        So as you can see, it's quite possible for a function to *modify* it's
        params - it's just rebindings of params that won't have side effects
        outside the function's namespace.

        Now, there is the case of immutable types (int, strings, tuples, ....).
        As implied, one cannot modify objects of these types - just create them.
        So in order to have a function that "change the value" of an immutable
        object, you have to wrap it into a mutable object, ie:

        def getAnswer(alist ):
        alist[0] = "42"

        answer = ["answer is ?"]
        getAnswer(answe r)
        print "answer is : ", answer[0]

        (snip)
        [color=blue]
        > In Python, there does not seem to be an easy way to have functions return
        > multiple values except it can return a list such as:
        > strHostname, nPortNumber, status = get_network_inf o (strIpAddress,
        > strHostname,
        > nPortNumber)
        > Am I missing something obvious? Is there a better, or more standard way
        > to return values from functions?[/color]

        This *is* the 'standard' (ie: idiomatic) way to return multiple values
        from a function. The C idiom of passing pointers to variables that are
        to be modified comes from C's limitations, namely no exception handling
        and only one return value[1], which leads to using the return value as a
        status report and relying on side effect for useful values.



        [1] To be pedantic, Python only allows one return value too - but this
        value can be a tuple or list, and then one can take advantage of
        tuple/list expansions that allows multiple assignment...

        HTH
        --
        bruno desthuilliers
        python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
        p in 'onurb@xiludom. gro'.split('@')])"

        Comment

        • Sion Arrowsmith

          #5
          Re: Python function returns:

          Michael Yanowitz <m.yanowitz@kea rfott.com> wrote:[color=blue]
          > In Python, there does not seem to be an easy way to have functions return
          >multiple values except it can return a list such as:
          >strHostname, nPortNumber, status = get_network_inf o (strIpAddress,
          >strHostname,
          > nPortNumber)
          > Am I missing something obvious? Is there a better, or more standard way
          >to return values from functions?[/color]

          I'm kind of repeating what other people have said, but there
          isn't a better way. Not just in Python, but in any language.
          If your function is returning multiple values, why should you
          have to split them into one privileged "return value" plus a
          bunch of Out (or InOut) parameters? That's a historical mis-
          feature of older languages, and one which more newer languages
          would do well to fix.

          --
          \S -- siona@chiark.gr eenend.org.uk -- http://www.chaos.org.uk/~sion/
          ___ | "Frankly I have no feelings towards penguins one way or the other"
          \X/ | -- Arthur C. Clarke
          her nu becomeþ se bera eadward ofdun hlæddre heafdes bæce bump bump bump

          Comment

          Working...