1

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()
6
  • 1
    It would help if you showed more context of how you intend to use the Parser class and redefine token_functions for each instance. Commented Dec 17, 2022 at 17:06
  • @YevhenKuzmovych It will give you an errorNameError. Commented Dec 17, 2022 at 17:12
  • Oh, right, Parser is not defined yet. Commented Dec 17, 2022 at 17:12
  • @YevhenKuzmovych Yeah but you can access it in any function__init__, new_line, Or, lambda. Commented Dec 17, 2022 at 17:13
  • Probably user gets an error because the self is not defined Yet. Commented Dec 17, 2022 at 17:14

1 Answer 1

1

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')}
Sign up to request clarification or add additional context in comments.

2 Comments

This works. Just out of curiosity. Is this the same as token_functions = {r'\n': lambda obj: Parser.new_line(obj)}? Both seem to work.
More or less. The difference come up if you decide to subclass Parser, in which case self.new_line() would a subclass's override of new_line be used.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.