[Python-Dev] Clean way in python to test for None, empty, scalar, and list/ndarray? A prayer to the gods of Python (original) (raw)
Oscar Benjamin oscar.j.benjamin at gmail.com
Sat Jun 15 17:12:38 CEST 2013
- Previous message: [Python-Dev] Clean way in python to test for None, empty, scalar, and list/ndarray? A prayer to the gods of Python
- Next message: [Python-Dev] [Python-checkins] cpython: Closes issue 17947. Adds PEP-0435 (Enum, IntEnum) to the stdlib.
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Your questions/suggestions are off-topic for this list. This belongs on python-ideas.
On 14 June 2013 20:12, Martin Schultz <maschu09 at gmail.com> wrote:
2. Testing for empty lists or empty ndarrays: 4. Finding the number of elements in an object: 6. Detecting None values in a list:
Each of the problems above relates to wanting to use generic Python containers interchangeably with numpy arrays. The solution is simply not to do this; there are too many semantic inconsistencies for this interchangeability to be safe. Here are just a few of them:
import numpy as np [1, 2, 3] + [4, 5, 6] [1, 2, 3, 4, 5, 6] np.array([1, 2, 3]) + np.array([4, 5, 6]) array([5, 7, 9]) [1, 2, 3] * 3 [1, 2, 3, 1, 2, 3, 1, 2, 3] np.array([1, 2, 3]) * 3 array([3, 6, 9]) [[1, 2, 3], [4, 5, 6]] + [7, 8, 9] [[1, 2, 3], [4, 5, 6], 7, 8, 9] np.array([[1, 2, 3], [4, 5, 6]]) + np.array([7, 8, 9]) array([[ 8, 10, 12], [11, 13, 15]]) bool([1, 2, 3]) True bool(np.array([1, 2, 3])) Traceback (most recent call last): File "", line 1, in ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Numpy provides a very convenient function that will convert objects of all the mentioned types to ndarray objects: the numpy.array function. If you have a function and want to accept lists (of lists ...) and ndarrays interchangeably, simply convert your input with numpy.array at the start of the function i.e.:
def square(numbers): numbers = numpy.array(numbers) print(numbers.size, numbers.shape) # etc. return numbers ** 2 # Would be an error for a list of lists
3. Testing for scalar: 5. Forcing a scalar to become a 1-element list:
numbers = np.array(possibly_scalar_input) if not numbers.shape: print('Numbers was scalar: coercing...') numbers = np.array([numbers])
Usually it is bad design to have an API that interchangeably accepts scalars and sequences. There are some situations where it does make sense such as numpy's ufuncs. These are scalar mathematical functions that can operate distributively on lists of lists, ndarrays etc. and numpy provides a convenient way for you to define these yourself:
def square(x): ... return x ** 2 ... square = np.frompyfunc(square, 1, 1) square(2) 4 square([2]) array([4], dtype=object) square([2, 3, 4]) array([4, 9, 16], dtype=object) square([[2, 3, 4]]) array([[4, 9, 16]], dtype=object) square([[]]) array([], shape=(1, 0), dtype=object)
The frompyfunc function unfortunately doesn't quite work like a decorator but you can easily wrap it do so:
def ufunc(nin, nout): def wrapper_factory(func): return np.frompyfunc(func, nin, nout) return wrapper_factory
@ufunc(1, 1) def square(x): return x ** 2
Oscar
- Previous message: [Python-Dev] Clean way in python to test for None, empty, scalar, and list/ndarray? A prayer to the gods of Python
- Next message: [Python-Dev] [Python-checkins] cpython: Closes issue 17947. Adds PEP-0435 (Enum, IntEnum) to the stdlib.
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]