Skip to content

Instantly share code, notes, and snippets.

@jrheling
Created February 2, 2020 13:37
Show Gist options
  • Save jrheling/67a80dfe326d0666ef0328ee502616a1 to your computer and use it in GitHub Desktop.
Save jrheling/67a80dfe326d0666ef0328ee502616a1 to your computer and use it in GitHub Desktop.
"""explore pylint W0640"""
#
# A test of how a lambda used to filter a list works
# when the filter criteria var is defined in a loop.
#
# This was written because pylint was giving me
# warning W0640: cell-var-from-loop
# for a use of filter materially similar to the (greatly simplified)
# example below, and I wanted to know if it was actually something
# to be concerned about.
#
# references:
# * https://docs.pylint.org/en/1.6.0/features.html
# * https://stackoverflow.com/questions/2295290/what-do-lambda-function-closures-capture
# * https://docs.python.org/3/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result
LIST_OF_NUMS = [1, 5, 2, 3, 4, 5, 6, 7, 3, 8, 3, 9]
NUMS_TO_FIND = [3, 5, 7]
nums_found = []
for target_num in NUMS_TO_FIND:
# pylint: disable=cell-var-from-loop
found = list(filter(
lambda n: n == target_num,
LIST_OF_NUMS
))
# pylint: enable=cell-var-from-loop
nums_found.append(found)
print(nums_found) # [[3, 3, 3], [5, 5], [7]]
# Conclusion: the pylint warning is valid, in the sense that the lambda
# defined in the filter() call references the value target_num had when
# the lambda was called, not when it was created. So if I were to save a
# reference to that lambda and call it later, it would probably have surprising
# results.
#
# Here's an example of the code that would _not_ work as probably intended:
# LIST_OF_NUMS = [1, 5, 2, 3, 4, 5, 6, 7, 3, 8, 3, 9]
# NUMS_TO_FIND = [3, 5, 7]
#
# filter_lambdas = []
# for target_num in NUMS_TO_FIND:
# filter_lambdas.append(
# lambda n: n == target_num
# )
#
# nums_found = []
# for filtering_lambda in filter_lambdas:
# found = list(filter(
# filtering_lambda,
# LIST_OF_NUMS
# ))
# nums_found.append(found)
#
# print(nums_found) # [[7], [7], [7]]
# In the case above, though, the lambda is created and used immeidiately
# (by filter()), so the value of target_num in the closure around the lambda
# is as expected, and ignoring the warning appropriate.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment