Pass self automatically in lambda function?

Question:

Is there a way to automatically pass self to a lambda function in a class? I know I can pass self in the __init__ function but then I’m redefining token_functions for every instance of Parser. token_functions never changes so this seems quite inefficient. Is there a better way to do this?

class Parser:
    token_functions = {r'n': lambda: Parser.new_line(self)}

    def __init__(self):
        self.line_number = 0
        Parser.token_functions[r'n']()
    
    def new_line(self):
        self.line_number += 1
        print(self.line_number)
    
Parser()
Asked By: user2820068

||

Answers:

No. The function created by the lambda expression is not a class attribute, so the descriptor protocol is not triggered.

You could call its __get__ method directly, e.g. Parser.token_functions[r'n'].__get__(self, type(self))(), but you probably don’t want to be dealing with the low-level machinery directly.

Just define the function to accept an object with a new_line method as an explicit argument, and pass self when the time comes.

class Parser:
    token_functions = {r'n': lambda obj: obj.new_line()}

    def __init__(self):
        self.line_number = 0
        Parser.token_functions[r'n'](self)
    
    def new_line(self):
        self.line_number += 1
        print(self.line_number)

The operator module provides a methodcaller function to replace this use of a lambda expression.

token_functions = {'n': operator.methodcaller('new_line')}
Answered By: chepner
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.