mongol
mongol

Reputation: 3

partial function in connection

I have a class like this:

class Controller:
    def __init__(self, view):   
        self._view = view
        self._connectSignals()
    
    def _buildExpression(self, sub_exp):
        expression = self._view.displayText() + sub_exp
        self._view.setDisplayText(expression)
    
    def _connectSignals(self):
        for btnText, btn in self._view.btns.items():
            if btnText not in {'=', 'C'}:
                    btn.clicked.connect(partial(self._buildExpression,btnText))        
        self._view.btns['C'].clicked.connect(self._view.clearDisplay)
            

why this line of code:

btn.clicked.connect(partial(self._buildExpression,btnText)) 

cannot be converted into this line:

btn.clicked.connect(self._buildExpression(btnText))

instead of this, there 's an error - "argument 1 has unexpected type 'NoneType' "

Upvotes: 0

Views: 78

Answers (1)

eyllanesc
eyllanesc

Reputation: 244202

To understand the difference, you have to understand that:

btn.clicked.connect(self._buildExpression(btnText))

is equivalent to:

val = self._buildExpression(btnText)
btn.clicked.connect(val)

And as you can see, val is the value that the function returns and it is None, so the code is also equivalent to:

btn.clicked.connect(None)

And clearly the above will throw an exception since connect expects a callable but gets a None.

On the other hand, it should also be noted that the _buildExpression method is evaluated before the connection is created and that is what you do not want, since what you want is that it is evaluated when the signal is emited.


Instead functools.partial creates a new function where it passes the arguments, something like:

def new_function():
    self._buildExpression(btnText)

btn.clicked.connect(new_function)

Upvotes: 1

Related Questions