diff --git a/asv_bench/benchmarks/libs.py b/asv_bench/benchmarks/libs.py new file mode 100644 index 0000000000000..f5c2397945cea --- /dev/null +++ b/asv_bench/benchmarks/libs.py @@ -0,0 +1,42 @@ +""" +Benchmarks for code in pandas/_libs, excluding pandas/_libs/tslibs, +which has its own directory +""" +import numpy as np + +from pandas._libs.lib import ( + is_list_like, + is_scalar, +) + +from pandas import ( + NA, + NaT, +) + +# TODO: share with something in pd._testing? +scalars = [ + 0, + 1.0, + 1 + 2j, + True, + "foo", + b"bar", + None, + np.datetime64(123, "ns"), + np.timedelta64(123, "ns"), + NaT, + NA, +] +zero_dims = [np.array("123")] +listlikes = [np.array([1, 2, 3]), {0: 1}, {1, 2, 3}, [1, 2, 3], (1, 2, 3)] + + +class ScalarListLike: + params = scalars + zero_dims + listlikes + + def time_is_list_like(self, param): + is_list_like(param) + + def time_is_scalar(self, param): + is_scalar(param) diff --git a/pandas/_libs/lib.pyx b/pandas/_libs/lib.pyx index 3a64ecb7a8a18..9f2c82d760785 100644 --- a/pandas/_libs/lib.pyx +++ b/pandas/_libs/lib.pyx @@ -1059,11 +1059,12 @@ def is_list_like(obj: object, allow_sets: bool = True) -> bool: cdef inline bint c_is_list_like(object obj, bint allow_sets) except -1: return ( - isinstance(obj, abc.Iterable) + # equiv: `isinstance(obj, abc.Iterable)` + hasattr(obj, "__iter__") and not isinstance(obj, type) # we do not count strings/unicode/bytes as list-like and not isinstance(obj, (str, bytes)) # exclude zero-dimensional numpy arrays, effectively scalars - and not (util.is_array(obj) and obj.ndim == 0) + and not cnp.PyArray_IsZeroDim(obj) # exclude sets if allow_sets is False and not (allow_sets is False and isinstance(obj, abc.Set)) )