3

I am new in Python so please bear with my naive question.

I want to write a function which takes a vector of numbers and computes their average value. So I write a little function as

def my_mean(*args):
    if len(args) == 0:
        return None
    else:
        total = sum(args)
        ave = 1.0 * total / len(args)
        return ave

my_mean(1, 2, 3)
2.0

But this function won't work if the argument is a list of numbers. For example,

my_mean([1, 2, 3])
Traceback (most recent call last):
  File "/usr/lib/wingide-101-4.1/src/debug/tserver/_sandbox.py", line 1, in <module>
    # Used internally for debug sandbox under external interpreter
  File "/usr/lib/wingide-101-4.1/src/debug/tserver/_sandbox.py", line 21, in my_mean
TypeError: unsupported operand type(s) for +: 'int' and 'list'

I know NumPy has a function numpy.mean which takes a list as argument but not a vector of numbers as my_mean does.

I am wondering if there is a way to make my_mean work in both cases? So:

my_mean(1, 2, 3)
2.0
my_mean([1, 2, 3])
2.0

just like min or max function?

pd40
  • 3,187
  • 3
  • 20
  • 29
JACKY88
  • 3,391
  • 5
  • 32
  • 48

2 Answers2

6

You can pass in your list by using the *arg syntax:

my_mean(*[1, 2, 3])

Alternatively, you could detect if your first argument passed in is a sequence and use that instead of the whole args tuple:

import collections

def my_mean(*args):
    if not args:
        return None
    if len(args) == 1 and isinstance(args[0], collections.Container):
        args = args[0]
    total = sum(args)
    ave = 1.0 * total / len(args)
    return ave
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • ah nice, didn't think about the collection abcs. I would make a check for _exactly_ one argument though. otherwise ``my_mean([1, 2, 3], 4)`` would behave unexpected (I'd expect it to error, in fact) – Jonas Schäfer Sep 23 '12 at 09:42
  • @JonasWielicki: indeed; updated the empty args test too to be simpler. – Martijn Pieters Sep 23 '12 at 09:45
  • Thanks for the quick reply. I know if I use `my_mean(1, 2, 3)`, Python collects all parameters and passes them as a list to `args`, so in the function `args` is a list of `[1, 2, 3]`. I don't understand the use of `my_mean(*[1, 2, 3])`. Why add a `*` there? Could you explain a little bit more? I can't find it in my book (a very introductory book). – JACKY88 Sep 23 '12 at 11:54
  • 1
    See [*args and **kwargs?](http://stackoverflow.com/q/3394835) and http://docs.python.org/reference/expressions.html#calls – Martijn Pieters Sep 23 '12 at 11:57
1

Why not pass your list in the form of Tuple? Use func(*[1, 2, 3])

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525