⚡️ Speed up function is_empty_indexer by 42%
#333
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
📄 42% (0.42x) speedup for
is_empty_indexerinpandas/core/indexers/utils.py⏱️ Runtime :
803 microseconds→566 microseconds(best of97runs)📝 Explanation and details
The optimized version achieves a 41% speedup through several key performance optimizations:
Primary optimizations:
Fast-path for numpy arrays: The most significant improvement comes from checking
isinstance(indexer, np.ndarray)first and using.sizeinstead oflen(). NumPy arrays are common indexers, and.sizeis faster thanlen()for ndarrays. This optimization particularly shines in test cases with large numpy arrays (55% faster fortest_large_nonempty_numpy_array).String/bytes exclusion: Added explicit exclusion of strings and bytes from list-like treatment using
not isinstance(indexer, (str, bytes)). This prevents unnecessary processing of string indexers, improving performance by 6-13% for string test cases.Avoiding generator expression overhead: Replaced the
any()call with generator expression with a simple for-loop and early return. This eliminates the overhead of creating a generator object and callingany(), providing substantial speedups for large tuples (31-80% faster for large tuple test cases).Local variable caching: Cached
np.ndarrayas a local variablendarrayin the loop to avoid repeated attribute lookups, providing a minor but consistent speedup.Consistent use of
.size: Used.sizeinstead oflen()for all numpy array size checks, which is the optimal approach for numpy arrays.Performance characteristics:
The optimizations target the most performance-critical paths while maintaining identical behavior and correctness across all test cases.
✅ Correctness verification report:
🌀 Generated Regression Tests and Runtime
import pytest # used for our unit tests
from pandas.core.indexers.utils import is_empty_indexer
-----------------------
Basic Test Cases
-----------------------
def test_empty_list():
# Empty list is an empty indexer
codeflash_output = is_empty_indexer([]) # 950ns -> 1.73μs (45.2% slower)
def test_empty_tuple():
# Empty tuple is an empty indexer
codeflash_output = is_empty_indexer(()) # 1.38μs -> 2.06μs (32.9% slower)
def test_empty_numpy_array():
# Empty numpy array is an empty indexer
import numpy as np
codeflash_output = is_empty_indexer(np.array([])) # 953ns -> 1.06μs (10.5% slower)
def test_non_empty_list():
# Non-empty list is not an empty indexer
codeflash_output = is_empty_indexer([1, 2, 3]) # 2.16μs -> 2.11μs (2.13% faster)
def test_non_empty_tuple():
# Non-empty tuple is not an empty indexer
codeflash_output = is_empty_indexer((1, 2, 3)) # 2.66μs -> 2.55μs (4.27% faster)
def test_non_empty_numpy_array():
# Non-empty numpy array is not an empty indexer
import numpy as np
codeflash_output = is_empty_indexer(np.array([1, 2, 3])) # 2.16μs -> 1.54μs (40.6% faster)
def test_scalar_integer():
# Scalar integer is not an empty indexer
codeflash_output = is_empty_indexer(5) # 2.14μs -> 1.98μs (8.45% faster)
def test_scalar_string():
# Scalar string is not an empty indexer
codeflash_output = is_empty_indexer("foo") # 2.08μs -> 1.84μs (13.0% faster)
def test_boolean():
# Scalar boolean is not an empty indexer
codeflash_output = is_empty_indexer(True) # 1.98μs -> 1.83μs (8.12% faster)
-----------------------
Edge Test Cases
-----------------------
def test_list_with_empty_numpy_array():
# List containing an empty numpy array is not itself empty, but the array is
import numpy as np
codeflash_output = is_empty_indexer([np.array([])]) # 1.80μs -> 2.05μs (12.1% slower)
def test_tuple_with_empty_numpy_array():
# Tuple containing an empty numpy array should be considered empty indexer
import numpy as np
codeflash_output = is_empty_indexer((np.array([]),)) # 2.91μs -> 2.71μs (7.43% faster)
def test_tuple_with_mixed_empty_and_nonempty_numpy_arrays():
# Tuple with one empty and one non-empty numpy array is considered empty indexer
import numpy as np
codeflash_output = is_empty_indexer((np.array([1]), np.array([]))) # 2.83μs -> 2.67μs (6.07% faster)
def test_tuple_with_all_nonempty_numpy_arrays():
# Tuple with all non-empty numpy arrays is not an empty indexer
import numpy as np
codeflash_output = is_empty_indexer((np.array([1]), np.array([2]))) # 2.50μs -> 2.63μs (4.98% slower)
def test_tuple_with_scalar_and_empty_numpy_array():
# Tuple with scalar and empty numpy array is considered empty indexer
import numpy as np
codeflash_output = is_empty_indexer((5, np.array([]))) # 2.83μs -> 2.64μs (7.35% faster)
def test_tuple_with_scalar_and_nonempty_numpy_array():
# Tuple with scalar and non-empty numpy array is not an empty indexer
import numpy as np
codeflash_output = is_empty_indexer((5, np.array([1]))) # 2.47μs -> 2.62μs (5.47% slower)
def test_tuple_with_only_scalars():
# Tuple with only scalars is not an empty indexer
codeflash_output = is_empty_indexer((1, 2, 3)) # 2.41μs -> 2.34μs (3.16% faster)
def test_empty_set():
# Empty set is considered empty indexer (list-like and len == 0)
codeflash_output = is_empty_indexer(set()) # 1.13μs -> 1.99μs (43.2% slower)
def test_nonempty_set():
# Non-empty set is not an empty indexer
codeflash_output = is_empty_indexer({1, 2}) # 2.37μs -> 2.41μs (1.50% slower)
def test_empty_dict():
# Empty dict is considered empty indexer (list-like and len == 0)
codeflash_output = is_empty_indexer({}) # 1.21μs -> 1.99μs (39.0% slower)
def test_nonempty_dict():
# Non-empty dict is not an empty indexer
codeflash_output = is_empty_indexer({'a': 1}) # 2.39μs -> 2.37μs (0.886% faster)
def test_string_is_not_empty_indexer():
# String is not list-like for indexing purposes
codeflash_output = is_empty_indexer('') # 2.13μs -> 2.00μs (6.19% faster)
codeflash_output = is_empty_indexer('abc') # 694ns -> 639ns (8.61% faster)
def test_bytes_is_not_empty_indexer():
# Bytes are not list-like for indexing purposes
codeflash_output = is_empty_indexer(b'') # 2.16μs -> 1.94μs (11.1% faster)
codeflash_output = is_empty_indexer(b'abc') # 848ns -> 755ns (12.3% faster)
def test_tuple_with_empty_list():
# Tuple with empty list is not considered empty indexer
# Because only empty numpy arrays in tuple trigger True
codeflash_output = is_empty_indexer(([],)) # 2.27μs -> 2.40μs (5.37% slower)
def test_tuple_with_empty_tuple():
# Tuple with empty tuple is not considered empty indexer
codeflash_output = is_empty_indexer(((),)) # 2.23μs -> 2.15μs (4.05% faster)
def test_tuple_with_multiple_types_including_empty_numpy_array():
# Tuple with mixed types, one of which is empty numpy array
import numpy as np
codeflash_output = is_empty_indexer(('foo', np.array([]), 5)) # 2.92μs -> 2.73μs (7.11% faster)
def test_tuple_with_multiple_empty_numpy_arrays():
# Tuple with multiple empty numpy arrays is considered empty indexer
import numpy as np
codeflash_output = is_empty_indexer((np.array([]), np.array([]))) # 2.60μs -> 2.56μs (1.41% faster)
def test_tuple_with_empty_and_nonempty_collections():
# Tuple with empty list and non-empty numpy array is not empty indexer
import numpy as np
codeflash_output = is_empty_indexer(([], np.array([1]))) # 2.49μs -> 2.60μs (4.27% slower)
def test_tuple_with_empty_numpy_array_and_empty_list():
# Tuple with empty numpy array and empty list is considered empty indexer
import numpy as np
codeflash_output = is_empty_indexer((np.array([]), [])) # 2.55μs -> 2.41μs (5.81% faster)
def test_tuple_with_empty_numpy_array_and_empty_tuple():
# Tuple with empty numpy array and empty tuple is considered empty indexer
import numpy as np
codeflash_output = is_empty_indexer((np.array([]), ())) # 2.57μs -> 2.40μs (7.12% faster)
def test_object_with_len_but_not_iterable():
# Custom object with len but not iterable, and len==0
class Dummy:
def len(self): return 0
d = Dummy()
codeflash_output = is_empty_indexer(d) # 2.21μs -> 2.03μs (8.98% faster)
def test_object_with_len_nonzero():
# Custom object with len returning nonzero
class Dummy:
def len(self): return 5
d = Dummy()
codeflash_output = is_empty_indexer(d) # 3.04μs -> 2.84μs (6.75% faster)
-----------------------
Large Scale Test Cases
-----------------------
def test_large_empty_numpy_array():
# Large empty numpy array (shape (0, 100)) is considered empty indexer
import numpy as np
arr = np.empty((0, 100))
codeflash_output = is_empty_indexer(arr) # 1.07μs -> 972ns (9.98% faster)
def test_large_nonempty_numpy_array():
# Large non-empty numpy array is not empty indexer
import numpy as np
arr = np.arange(1000)
codeflash_output = is_empty_indexer(arr) # 2.71μs -> 1.75μs (55.0% faster)
def test_large_list():
# Large non-empty list is not empty indexer
arr = list(range(1000))
codeflash_output = is_empty_indexer(arr) # 2.24μs -> 2.46μs (9.25% slower)
def test_large_tuple_with_one_empty_numpy_array():
# Large tuple with one empty numpy array is considered empty indexer
import numpy as np
tup = tuple(np.arange(10) for _ in range(999)) + (np.array([]),)
codeflash_output = is_empty_indexer(tup) # 61.4μs -> 46.7μs (31.4% faster)
def test_large_tuple_all_nonempty_numpy_arrays():
# Large tuple with all non-empty numpy arrays is not empty indexer
import numpy as np
tup = tuple(np.arange(10) for _ in range(1000))
codeflash_output = is_empty_indexer(tup) # 61.0μs -> 46.3μs (31.7% faster)
def test_large_tuple_with_empty_list():
# Large tuple with one empty list is not considered empty indexer
tup = tuple([list(range(10)) for _ in range(999)] + [[]])
codeflash_output = is_empty_indexer(tup) # 54.7μs -> 30.4μs (79.9% faster)
def test_large_tuple_with_empty_numpy_array_and_other_types():
# Large tuple with empty numpy array and other types is considered empty indexer
import numpy as np
tup = tuple(range(998)) + (np.array([]), 'foo')
codeflash_output = is_empty_indexer(tup) # 54.6μs -> 30.2μs (80.4% faster)
def test_large_empty_list():
# Large empty list (but actually empty) is considered empty indexer
arr = []
codeflash_output = is_empty_indexer(arr) # 846ns -> 1.66μs (48.9% slower)
def test_large_empty_tuple():
# Large empty tuple (but actually empty) is considered empty indexer
arr = ()
codeflash_output = is_empty_indexer(arr) # 1.34μs -> 2.06μs (34.9% slower)
codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
import pytest # used for our unit tests
from pandas.core.indexers.utils import is_empty_indexer
unit tests
1. Basic Test Cases
def test_empty_list():
# Basic: empty list should return True
codeflash_output = is_empty_indexer([]) # 1.18μs -> 2.07μs (43.2% slower)
def test_nonempty_list():
# Basic: non-empty list should return False
codeflash_output = is_empty_indexer([1, 2, 3]) # 2.37μs -> 2.20μs (7.54% faster)
def test_empty_tuple():
# Basic: empty tuple should return True
codeflash_output = is_empty_indexer(()) # 1.47μs -> 2.31μs (36.5% slower)
def test_nonempty_tuple():
# Basic: non-empty tuple should return False
codeflash_output = is_empty_indexer((1,)) # 2.47μs -> 2.38μs (3.61% faster)
def test_empty_set():
# Basic: empty set should return True
codeflash_output = is_empty_indexer(set()) # 1.40μs -> 2.24μs (37.6% slower)
def test_nonempty_set():
# Basic: non-empty set should return False
codeflash_output = is_empty_indexer({1, 2}) # 2.48μs -> 2.58μs (3.65% slower)
def test_empty_dict():
# Basic: empty dict should return True
codeflash_output = is_empty_indexer({}) # 1.29μs -> 2.09μs (37.9% slower)
def test_nonempty_dict():
# Basic: non-empty dict should return False
codeflash_output = is_empty_indexer({'a': 1}) # 2.50μs -> 2.42μs (3.18% faster)
def test_empty_range():
# Basic: empty range should return True
codeflash_output = is_empty_indexer(range(0)) # 1.21μs -> 2.08μs (41.8% slower)
def test_nonempty_range():
# Basic: non-empty range should return False
codeflash_output = is_empty_indexer(range(5)) # 2.50μs -> 2.43μs (3.05% faster)
def test_single_none():
# Basic: None is not list-like, so should return False
codeflash_output = is_empty_indexer(None) # 2.01μs -> 1.81μs (10.5% faster)
def test_single_int():
# Basic: int is not list-like, so should return False
codeflash_output = is_empty_indexer(42) # 2.04μs -> 1.88μs (8.72% faster)
def test_single_str():
# Basic: string is not considered list-like, so should return False
codeflash_output = is_empty_indexer("hello") # 2.02μs -> 1.95μs (4.06% faster)
def test_empty_str():
# Basic: empty string is not considered list-like, so should return False
codeflash_output = is_empty_indexer("") # 2.03μs -> 1.83μs (10.8% faster)
def test_tuple_with_empty_list():
# Basic: tuple containing an empty list should return True
codeflash_output = is_empty_indexer(([ ],)) # 2.46μs -> 2.54μs (3.31% slower)
def test_tuple_with_nonempty_list():
# Basic: tuple containing a non-empty list should return False
codeflash_output = is_empty_indexer(([1],)) # 2.30μs -> 2.35μs (2.21% slower)
def test_tuple_with_empty_tuple():
# Basic: tuple containing an empty tuple should return True
codeflash_output = is_empty_indexer(((),)) # 2.26μs -> 2.33μs (2.96% slower)
def test_tuple_with_nonempty_tuple():
# Basic: tuple containing a non-empty tuple should return False
codeflash_output = is_empty_indexer(((1,),)) # 2.25μs -> 2.32μs (3.01% slower)
def test_tuple_with_empty_set():
# Basic: tuple containing an empty set should return True
codeflash_output = is_empty_indexer((set(),)) # 2.32μs -> 2.46μs (5.77% slower)
def test_tuple_with_nonempty_set():
# Basic: tuple containing a non-empty set should return False
codeflash_output = is_empty_indexer(({1},)) # 2.30μs -> 2.37μs (2.95% slower)
def test_tuple_with_empty_dict():
# Basic: tuple containing an empty dict should return True
codeflash_output = is_empty_indexer(({},)) # 2.11μs -> 2.26μs (6.52% slower)
def test_tuple_with_nonempty_dict():
# Basic: tuple containing a non-empty dict should return False
codeflash_output = is_empty_indexer(({'a': 1},)) # 2.27μs -> 2.38μs (4.59% slower)
def test_tuple_with_empty_range():
# Basic: tuple containing an empty range should return True
codeflash_output = is_empty_indexer((range(0),)) # 2.23μs -> 2.22μs (0.585% faster)
def test_tuple_with_nonempty_range():
# Basic: tuple containing a non-empty range should return False
codeflash_output = is_empty_indexer((range(1),)) # 2.32μs -> 2.35μs (1.11% slower)
def test_tuple_with_none():
# Basic: tuple containing None should return False
codeflash_output = is_empty_indexer((None,)) # 2.27μs -> 2.17μs (4.28% faster)
def test_tuple_with_int():
# Basic: tuple containing an int should return False
codeflash_output = is_empty_indexer((42,)) # 2.26μs -> 2.35μs (4.16% slower)
def test_tuple_with_str():
# Basic: tuple containing a string should return False
codeflash_output = is_empty_indexer(("abc",)) # 2.22μs -> 2.15μs (3.20% faster)
def test_tuple_with_empty_str():
# Basic: tuple containing an empty string should return False
codeflash_output = is_empty_indexer(("",)) # 2.23μs -> 2.29μs (2.62% slower)
def test_tuple_with_mixed_empty_and_nonempty():
# Basic: tuple with both empty and non-empty list-like objects should return True if any is empty
codeflash_output = is_empty_indexer(([], [1, 2])) # 2.33μs -> 2.18μs (6.59% faster)
codeflash_output = is_empty_indexer(([1], [])) # 868ns -> 865ns (0.347% faster)
codeflash_output = is_empty_indexer((set(), {1})) # 602ns -> 572ns (5.24% faster)
codeflash_output = is_empty_indexer((range(0), range(1))) # 550ns -> 551ns (0.181% slower)
def test_tuple_with_multiple_nonempty():
# Basic: tuple with multiple non-empty list-like objects should return False
codeflash_output = is_empty_indexer(([1], [2])) # 2.22μs -> 2.13μs (3.89% faster)
codeflash_output = is_empty_indexer((set([1]), set([2]))) # 941ns -> 908ns (3.63% faster)
2. Edge Test Cases
def test_object_with_len_zero():
# Edge: custom object with len == 0 should return True
class Dummy:
def len(self):
return 0
codeflash_output = is_empty_indexer(Dummy()) # 2.15μs -> 2.06μs (4.32% faster)
def test_object_with_len_nonzero():
# Edge: custom object with len > 0 should return False
class Dummy:
def len(self):
return 5
codeflash_output = is_empty_indexer(Dummy()) # 2.12μs -> 1.88μs (12.6% faster)
def test_tuple_with_custom_object_len_zero():
# Edge: tuple containing custom object with len == 0 should return True
class Dummy:
def len(self):
return 0
codeflash_output = is_empty_indexer((Dummy(),)) # 2.27μs -> 2.63μs (13.4% slower)
def test_tuple_with_custom_object_len_nonzero():
# Edge: tuple containing custom object with len > 0 should return False
class Dummy:
def len(self):
return 3
codeflash_output = is_empty_indexer((Dummy(),)) # 2.44μs -> 2.54μs (4.17% slower)
def test_tuple_with_multiple_custom_objects():
# Edge: tuple with multiple custom objects, one with len == 0
class DummyZero:
def len(self):
return 0
class DummyNonZero:
def len(self):
return 2
codeflash_output = is_empty_indexer((DummyZero(), DummyNonZero())) # 2.60μs -> 2.69μs (3.53% slower)
def test_tuple_with_all_custom_objects_nonzero():
# Edge: tuple with multiple custom objects, all with len > 0
class DummyA:
def len(self):
return 1
class DummyB:
def len(self):
return 2
codeflash_output = is_empty_indexer((DummyA(), DummyB())) # 2.60μs -> 2.71μs (3.84% slower)
def test_tuple_with_non_listlike_objects():
# Edge: tuple with non-list-like objects (int, None, float)
codeflash_output = is_empty_indexer((None, 1, 2.5)) # 2.55μs -> 2.65μs (3.48% slower)
def test_tuple_with_empty_and_non_listlike():
# Edge: tuple with both empty list-like and non-list-like objects
codeflash_output = is_empty_indexer(([], 42)) # 2.43μs -> 2.48μs (1.90% slower)
codeflash_output = is_empty_indexer((set(), None)) # 905ns -> 832ns (8.77% faster)
def test_tuple_with_multiple_empty_listlike():
# Edge: tuple with multiple empty list-like objects
codeflash_output = is_empty_indexer(([], (), set())) # 2.31μs -> 2.19μs (5.61% faster)
def test_tuple_with_empty_list_and_empty_dict():
# Edge: tuple with empty list and empty dict
codeflash_output = is_empty_indexer(([], {})) # 2.28μs -> 2.11μs (8.35% faster)
def test_tuple_with_empty_range_and_empty_set():
# Edge: tuple with empty range and empty set
codeflash_output = is_empty_indexer((range(0), set())) # 2.19μs -> 2.32μs (5.65% slower)
def test_tuple_with_empty_and_empty_str():
# Edge: tuple with empty list and empty string (string not considered list-like)
codeflash_output = is_empty_indexer(([], "")) # 2.31μs -> 2.30μs (0.435% faster)
def test_tuple_with_only_empty_str():
# Edge: tuple with only empty string (should be False)
codeflash_output = is_empty_indexer(("",)) # 2.22μs -> 2.24μs (0.803% slower)
def test_tuple_with_empty_list_and_empty_custom_object():
# Edge: tuple with empty list and custom object with len == 0
class Dummy:
def len(self):
return 0
codeflash_output = is_empty_indexer(([], Dummy())) # 2.57μs -> 2.63μs (2.36% slower)
def test_tuple_with_empty_dict_and_non_listlike():
# Edge: tuple with empty dict and int
codeflash_output = is_empty_indexer(({}, 123)) # 2.29μs -> 2.26μs (1.19% faster)
def test_tuple_with_empty_range_and_non_listlike():
# Edge: tuple with empty range and float
codeflash_output = is_empty_indexer((range(0), 3.14)) # 2.29μs -> 2.36μs (2.97% slower)
3. Large Scale Test Cases
def test_large_empty_list():
# Large scale: large empty list (length 0)
large_empty = []
codeflash_output = is_empty_indexer(large_empty) # 841ns -> 1.59μs (47.0% slower)
def test_large_nonempty_list():
# Large scale: large non-empty list (length 1000)
large_nonempty = list(range(1000))
codeflash_output = is_empty_indexer(large_nonempty) # 2.10μs -> 2.15μs (2.10% slower)
def test_large_empty_tuple():
# Large scale: large empty tuple (length 0)
large_empty_tuple = tuple()
codeflash_output = is_empty_indexer(large_empty_tuple) # 1.37μs -> 2.14μs (36.1% slower)
def test_large_nonempty_tuple():
# Large scale: large non-empty tuple (length 1000)
large_nonempty_tuple = tuple(range(1000))
codeflash_output = is_empty_indexer(large_nonempty_tuple) # 54.0μs -> 29.9μs (80.6% faster)
def test_tuple_of_large_empty_lists():
# Large scale: tuple of 1000 empty lists
tuple_of_empty_lists = tuple([] for _ in range(1000))
codeflash_output = is_empty_indexer(tuple_of_empty_lists) # 53.8μs -> 30.4μs (76.9% faster)
def test_tuple_of_large_nonempty_lists():
# Large scale: tuple of 1000 non-empty lists
tuple_of_nonempty_lists = tuple([i] for i in range(1000))
codeflash_output = is_empty_indexer(tuple_of_nonempty_lists) # 53.6μs -> 30.8μs (74.4% faster)
def test_tuple_with_one_large_empty_list():
# Large scale: tuple with one large empty list and others non-empty
tuple_with_one_empty = ([ ], [1], [2])
codeflash_output = is_empty_indexer(tuple_with_one_empty) # 2.53μs -> 2.65μs (4.52% slower)
def test_tuple_with_one_large_nonempty_list():
# Large scale: tuple with one large non-empty list and others empty
tuple_with_one_nonempty = ([1]*1000, [], [])
codeflash_output = is_empty_indexer(tuple_with_one_nonempty) # 2.51μs -> 2.51μs (0.159% faster)
def test_tuple_with_large_mixed_listlike():
# Large scale: tuple with 999 non-empty lists and 1 empty list
tuple_mixed = tuple([i] for i in range(999)) + ([],)
codeflash_output = is_empty_indexer(tuple_mixed) # 54.1μs -> 30.0μs (80.5% faster)
def test_tuple_with_large_mixed_nonempty():
# Large scale: tuple with 1000 non-empty lists
tuple_nonempty = tuple([i] for i in range(1000))
codeflash_output = is_empty_indexer(tuple_nonempty) # 54.2μs -> 29.9μs (81.4% faster)
def test_tuple_with_large_mixed_empty_custom_objects():
# Large scale: tuple with 999 custom objects with len > 0 and 1 with len == 0
class Dummy:
def init(self, n):
self.n = n
def len(self):
return self.n
tuple_custom = tuple(Dummy(1) for _ in range(999)) + (Dummy(0),)
codeflash_output = is_empty_indexer(tuple_custom) # 54.3μs -> 30.7μs (76.8% faster)
def test_tuple_with_large_mixed_nonempty_custom_objects():
# Large scale: tuple with 1000 custom objects with len > 0
class Dummy:
def init(self, n):
self.n = n
def len(self):
return self.n
tuple_custom = tuple(Dummy(i+1) for i in range(1000))
codeflash_output = is_empty_indexer(tuple_custom) # 54.7μs -> 31.4μs (74.5% faster)
codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
To edit these changes
git checkout codeflash/optimize-is_empty_indexer-mhw86jw6and push.