What is the difference between "binding to variables" and "binding to an object" in Python

When I learned "name and binding" in Python, I saw the following example:

>>> def testClosure(maxIndex):
        def closureTest(maxIndex=maxIndex):
            return maxIndex
        maxIndex += 5
        return closureTest()
>>> print(testClosure(10))
10


>>> def testClosure(maxIndex):
        def closureTest():
            return maxIndex
       maxIndex += 5
       return closureTest()
>>> print(testClosure(10))
15

The author explained this as: In the last function, a free variable in the inner region is bound to a variable in the outer region, and not to objects.

Then my question is: what's the difference between "bind to variable" and "bind to object" in Python?

It’s also very difficult: the result will be different if I reorder the code.

>>> def testClosure(maxIndex):
        maxIndex += 5
        def closureTest(maxIndex=maxIndex):
            return maxIndex
        return closureTest()

>>> print(testClosure(10))
15

Thanks in advance.

+3
source share
3 answers

, , "def" . 'def closTest (maxIndex = maxIndex):' 'if' 'while', ( ).

'def' , ( /). , . , (, maxIndex ), , , ( ) "def" .

, ( ) , . , , "def" .

. , . def maxIndex ( , ).

maxIndex , (re) -defined. , (re) - , .

Python - . "def" - ​​ , , . (, , "def" VM, ( ) ).

, '(myList = list()), . - , . , , . (, , - , - def).

, . , ; , . ; .

, . , , , ( Python).

+3

:

  • Python LEGB () . LEGB Local, Extended, , . , "" , , , , , , .
  • def closureTest(maxIndex=maxIndex):
        return maxIndex
    

    definition-time, run-time. definition-time , def - . run-time , . , , definition-time .


, maxIndex . , :

>>> def testClosure(maxIndex):              
        def closureTest(index=maxIndex):     # (1)
            return index                     
        maxIndex += 5
        return closureTest()                 # (2)
>>> print(testClosure(10))
  • (1) , - 10.
  • (2) closureTest() , index 10. , .

def testClosure(maxIndex):
    def closureTest():
        return maxIndex                 # (3)
   maxIndex += 5
   return closureTest()                 # (4)
print(testClosure(10))
  • (3) LEGB Python maxIndex . maxIndex , . maxIndex, testClosure.

  • (4) closureTest() maxIndex 15. , maxIndex, closureTest() 15.


>>> def testClosure(maxIndex):
        maxIndex += 5                           # (5)    
        def closureTest(maxIndex=maxIndex):     # (6)
            return maxIndex
        return closureTest()                    # (7)
  • (5) maxIndex 15

  • (6) TEST maxIndex 15 .

  • (7) closureTest() , maxIndex. 15 .

+8
>>> def testClosure(maxIndex):
        def closureTest(maxIndex=maxIndex): # You're creating a function with a kwarg of maxIndex
            return maxIndex                 # which references the int passed in from outside
        maxIndex += 5                       # Incrementing maxIndex means that the maxIndex in the outer
        return closureTest()                # scope now points to a different int.
>>> print(testClosure(10))
10

:

>>> a = b = 1
>>> a += 1
>>> a
2
>>> b
1

, "bind to the object" "bind to variable". "" - , a, , , b .

If you do not pass the value of maxIndex to the internal function and then request it, since it is not defined in the local scope, it searches in the extended scope.

I make a very big assumption here, but you can see the time difference that needs to be fulfilled, which I would tend to ascribe to the cost of this advanced search:

>>> import timeit
>>> def testClosure(maxIndex):
...     def closureTest(maxIndex=maxIndex):
...         return maxIndex
...     maxIndex += 5
...     return closureTest()
...
>>> def testClosure2(maxIndex):
...     def closureTest():
...         return maxIndex
...     maxIndex += 5
...     return closureTest()
...
>>> timeit.Timer('testClosure(10)','from __main__ import testClosure').timeit()
1.4626929759979248
>>> timeit.Timer('testClosure2(10)','from __main__ import testClosure2').timeit()
1.7869210243225098
0
source

Source: https://habr.com/ru/post/1779361/


All Articles