The reason why inputting f(2, 4) and f([2, 4]) does not work because, for the former, the function only accepts one argument and, for the latter, you are passing in a Python list.
Numpy arrays have more functionality. Python lists do not. You can see the difference when you look at their class methods:
>>> x = numpy.array([[2.0, 4.0]])
>>> dir(x)
['T', '__abs__', '__add__', '__and__', '__array__', '__array_finalize__', '__array_interface__', '__array_prepare__', '__array_priority__', '__array_struct__', '__array_wrap__', '__class__', '__contains__', '__copy__', '__deepcopy__', '__delattr__', '__delitem__', '__delslice__', '__div__', '__divmod__', '__doc__', '__eq__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__hex__', '__iadd__', '__iand__', '__idiv__', '__ifloordiv__', '__ilshift__', '__imod__', '__imul__', '__index__', '__init__', '__int__', '__invert__', '__ior__', '__ipow__', '__irshift__', '__isub__', '__iter__', '__itruediv__', '__ixor__', '__le__', '__len__', '__long__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__setitem__', '__setslice__', '__setstate__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__xor__', 'all', 'any', 'argmax', 'argmin', 'argpartition', 'argsort', 'astype', 'base', 'byteswap', 'choose', 'clip', 'compress', 'conj', 'conjugate', 'copy', 'ctypes', 'cumprod', 'cumsum', 'data', 'diagonal', 'dot', 'dtype', 'dump', 'dumps', 'fill', 'flags', 'flat', 'flatten', 'getfield', 'imag', 'item', 'itemset', 'itemsize', 'max', 'mean', 'min', 'nbytes', 'ndim', 'newbyteorder', 'nonzero', 'partition', 'prod', 'ptp', 'put', 'ravel', 'real', 'repeat', 'reshape', 'resize', 'round', 'searchsorted', 'setfield', 'setflags', 'shape', 'size', 'sort', 'squeeze', 'std', 'strides', 'sum', 'swapaxes', 'take', 'tobytes', 'tofile', 'tolist', 'tostring', 'trace', 'transpose', 'var', 'view']
>>> x = [2.0, 4.0]
>>> dir(x)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
Notice that the numpy array has a __pow__ method but the Python list does not. This is a special method that allows you to dictate how Python would use the ** function on the array. Therefore, the numpy array can be squared.
>>> x = [1, 2, 3]
>>> x**2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'int'
There are a few ways to go about this problem. You can either pass in a numpy array as Headcrab has said or make your function more complex. I will explain how to make a function that fits all three cases.
To deal with all three cases, you will have to check what the type of the data passed in is and you will have to accept multiple arguments.
def f(x, *args):
if args:
# If there are multiple arguments e.g. f(2, 4)
return [x**2] + [n**2 for n in args]
elif isinstance(x, list):
# If a Python list is passed e.g. f([2, 4])
return [n**2 for n in x]
else:
# If something else (probably numpy array) is passed e.g. f(numpy.array([2, 4]))
return x**2
Some test cases:
>>> f(1, 2)
[1, 4]
>>> f(2, 4)
[4, 16]
>>> f(3, 6)
[9, 36]
.
>>> f([1, 2])
[1, 4]
>>> f([2, 4])
[4, 16]
>>> f([3, 6])
[9, 36]
.
>>> f(numpy.array([1, 2]))
array([1, 4])
>>> f(numpy.arry([2, 4]))
array([ 4, 16])
>>> f(numpy.array([3, 6]))
array([ 9, 36])
f(numpy.array([2, 4]))