Python Lambdas and Variable Bindings

前端 未结 2 989
忘了有多久
忘了有多久 2020-11-29 09:50

I\'ve been working on a basic testing framework for an automated build. The piece of code below represents a simple test of communication between two machines using differe

相关标签:
2条回答
  • 2020-11-29 10:20

    The client variable is defined in the outer scope, so by the time the lambda is run it will always be set to the last client in the list.

    To get the intended result, you can give the lambda an argument with a default value:

    passIf = lambda client=client: client.returncode(CMD2) == 0
    

    Since the default value is evaluated at the time the lambda is defined, its value will remain correct.

    Another way is to create the lambda inside a function:

    def createLambda(client):
        return lambda: client.returncode(CMD2) == 0
    #...
    passIf = createLambda(client)
    

    Here the lambda refers to the client variable in the createLambda function, which has the correct value.

    0 讨论(0)
  • 2020-11-29 10:31

    What happens is that your passIf argument, the lambda, refers to the variable client from the enclosing scope. It doesn't refer to the object the variable client refers to when it is created, but the variable itself. If you call these passIf after the loop has ended, that means they all refer to the last value in the loop. (In closure terminology, Python's closures are late-binding, not early-binding.)

    Fortunately it's fairly easy to make a late-binding closure into an early-binding closure. You can do it by simply giving the lambda an argument with as default the value you want to bind:

    passIf = lambda client=client: client.returncode(CMD2) == 0
    

    That does mean the function gets that extra argument, and might mess things up if it gets called with an argument by accident -- or when you want the function to take arbitrary arguments. So another technique is to do it like this:

    # Before your loop:
    def make_passIf(client):
        return lambda: client.returncode(CMD2) == 0
    
    # In the loop
    t = Test(
        ...
        passIf = make_passIf(client)
    )
    
    0 讨论(0)
提交回复
热议问题