Don't understand why UnboundLocalError occurs [duplicate]












123
















This question already has an answer here:




  • How to change a variable after it is already defined?

    6 answers



  • Using global variables in a function

    18 answers




What am I doing wrong here?



counter = 0

def increment():
counter += 1

increment()


The above code throws an UnboundLocalError.










share|improve this question















marked as duplicate by Zero Piraeus python
Users with the  python badge can single-handedly close python questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Dec 29 '16 at 6:42


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.














  • 41





    @ZeroPiraeus: why did you hammer a question with 40k+ views, which is the first result for "UnboundLocalError" in Google, as a duplicate of a nearly identical new question that you answered instead of simply posting your answer here?

    – vaultah
    Jan 3 '17 at 0:26






  • 1





    This question and the one it's currently marked duplicate of are under discussion in the Python chatroom.

    – Zero Piraeus
    Jan 3 '17 at 1:30






  • 4





    Many of the answers here say to use global, and although that works, using modifiable globals is generally not recommend when other options exist.

    – PM 2Ring
    Jan 3 '17 at 1:34






  • 10





    @ZeroPiraeus A question asked in 2012 can't be a duplicate of a question asked in 2016 ... rather the newer one is the duplicate.

    – dsh
    Feb 14 '17 at 17:04






  • 5





    @dsh That's not true.

    – Zero Piraeus
    Feb 14 '17 at 18:03
















123
















This question already has an answer here:




  • How to change a variable after it is already defined?

    6 answers



  • Using global variables in a function

    18 answers




What am I doing wrong here?



counter = 0

def increment():
counter += 1

increment()


The above code throws an UnboundLocalError.










share|improve this question















marked as duplicate by Zero Piraeus python
Users with the  python badge can single-handedly close python questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Dec 29 '16 at 6:42


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.














  • 41





    @ZeroPiraeus: why did you hammer a question with 40k+ views, which is the first result for "UnboundLocalError" in Google, as a duplicate of a nearly identical new question that you answered instead of simply posting your answer here?

    – vaultah
    Jan 3 '17 at 0:26






  • 1





    This question and the one it's currently marked duplicate of are under discussion in the Python chatroom.

    – Zero Piraeus
    Jan 3 '17 at 1:30






  • 4





    Many of the answers here say to use global, and although that works, using modifiable globals is generally not recommend when other options exist.

    – PM 2Ring
    Jan 3 '17 at 1:34






  • 10





    @ZeroPiraeus A question asked in 2012 can't be a duplicate of a question asked in 2016 ... rather the newer one is the duplicate.

    – dsh
    Feb 14 '17 at 17:04






  • 5





    @dsh That's not true.

    – Zero Piraeus
    Feb 14 '17 at 18:03














123












123








123


35







This question already has an answer here:




  • How to change a variable after it is already defined?

    6 answers



  • Using global variables in a function

    18 answers




What am I doing wrong here?



counter = 0

def increment():
counter += 1

increment()


The above code throws an UnboundLocalError.










share|improve this question

















This question already has an answer here:




  • How to change a variable after it is already defined?

    6 answers



  • Using global variables in a function

    18 answers




What am I doing wrong here?



counter = 0

def increment():
counter += 1

increment()


The above code throws an UnboundLocalError.





This question already has an answer here:




  • How to change a variable after it is already defined?

    6 answers



  • Using global variables in a function

    18 answers








python global-variables scope






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 '18 at 23:00









martineau

68.9k1091186




68.9k1091186










asked Feb 13 '12 at 17:11









RandomblueRandomblue

36.2k119287505




36.2k119287505




marked as duplicate by Zero Piraeus python
Users with the  python badge can single-handedly close python questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Dec 29 '16 at 6:42


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.









marked as duplicate by Zero Piraeus python
Users with the  python badge can single-handedly close python questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Dec 29 '16 at 6:42


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.










  • 41





    @ZeroPiraeus: why did you hammer a question with 40k+ views, which is the first result for "UnboundLocalError" in Google, as a duplicate of a nearly identical new question that you answered instead of simply posting your answer here?

    – vaultah
    Jan 3 '17 at 0:26






  • 1





    This question and the one it's currently marked duplicate of are under discussion in the Python chatroom.

    – Zero Piraeus
    Jan 3 '17 at 1:30






  • 4





    Many of the answers here say to use global, and although that works, using modifiable globals is generally not recommend when other options exist.

    – PM 2Ring
    Jan 3 '17 at 1:34






  • 10





    @ZeroPiraeus A question asked in 2012 can't be a duplicate of a question asked in 2016 ... rather the newer one is the duplicate.

    – dsh
    Feb 14 '17 at 17:04






  • 5





    @dsh That's not true.

    – Zero Piraeus
    Feb 14 '17 at 18:03














  • 41





    @ZeroPiraeus: why did you hammer a question with 40k+ views, which is the first result for "UnboundLocalError" in Google, as a duplicate of a nearly identical new question that you answered instead of simply posting your answer here?

    – vaultah
    Jan 3 '17 at 0:26






  • 1





    This question and the one it's currently marked duplicate of are under discussion in the Python chatroom.

    – Zero Piraeus
    Jan 3 '17 at 1:30






  • 4





    Many of the answers here say to use global, and although that works, using modifiable globals is generally not recommend when other options exist.

    – PM 2Ring
    Jan 3 '17 at 1:34






  • 10





    @ZeroPiraeus A question asked in 2012 can't be a duplicate of a question asked in 2016 ... rather the newer one is the duplicate.

    – dsh
    Feb 14 '17 at 17:04






  • 5





    @dsh That's not true.

    – Zero Piraeus
    Feb 14 '17 at 18:03








41




41





@ZeroPiraeus: why did you hammer a question with 40k+ views, which is the first result for "UnboundLocalError" in Google, as a duplicate of a nearly identical new question that you answered instead of simply posting your answer here?

– vaultah
Jan 3 '17 at 0:26





@ZeroPiraeus: why did you hammer a question with 40k+ views, which is the first result for "UnboundLocalError" in Google, as a duplicate of a nearly identical new question that you answered instead of simply posting your answer here?

– vaultah
Jan 3 '17 at 0:26




1




1





This question and the one it's currently marked duplicate of are under discussion in the Python chatroom.

– Zero Piraeus
Jan 3 '17 at 1:30





This question and the one it's currently marked duplicate of are under discussion in the Python chatroom.

– Zero Piraeus
Jan 3 '17 at 1:30




4




4





Many of the answers here say to use global, and although that works, using modifiable globals is generally not recommend when other options exist.

– PM 2Ring
Jan 3 '17 at 1:34





Many of the answers here say to use global, and although that works, using modifiable globals is generally not recommend when other options exist.

– PM 2Ring
Jan 3 '17 at 1:34




10




10





@ZeroPiraeus A question asked in 2012 can't be a duplicate of a question asked in 2016 ... rather the newer one is the duplicate.

– dsh
Feb 14 '17 at 17:04





@ZeroPiraeus A question asked in 2012 can't be a duplicate of a question asked in 2016 ... rather the newer one is the duplicate.

– dsh
Feb 14 '17 at 17:04




5




5





@dsh That's not true.

– Zero Piraeus
Feb 14 '17 at 18:03





@dsh That's not true.

– Zero Piraeus
Feb 14 '17 at 18:03












8 Answers
8






active

oldest

votes


















132














Python doesn't have variable declarations, so it has to figure out the scope of variables itself. It does so by a simple rule: If there is an assignment to a variable inside a function, that variable is considered local.[1] Thus, the line



counter += 1


implicitly makes counter local to increment(). Trying to execute this line, though, will try to read the value of the local variable counter before it is assigned, resulting in an UnboundLocalError.[2]



If counter is a global variable, the global keyword will help. If increment() is a local function and counter a local variable, you can use nonlocal in Python 3.x.






share|improve this answer





















  • 5





    python 3 docs has a faq page on why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value via unboundlocalerror-local-variable-l-referenced-before-assignment-python

    – here
    May 4 '14 at 7:19













  • A note that caught me out, I had a variable declared at the top of the file that I can read inside a function without issue, however to write to a variable that I have declared at the top of the file, I had to use global.

    – mouckatron
    Feb 6 '18 at 14:35











  • A more in-depth explanation: docs.python.org/3.3/reference/…. Not only can assignments bind names, so can imports, so you may also get UnboundLocalError from a statement that uses an unbounded imported name. Example: def foo(): bar = deepcopy({'a':1}); from copy import deepcopy; return bar, then from copy import deepcopy; foo(). The call succeeds if the local import from copy import deepcopy is removed.

    – Yibo Yang
    Jun 27 '18 at 16:00





















68














You need to use the global statement so that you are modifying the global variable counter, instead of a local variable:



counter = 0

def increment():
global counter
counter += 1

increment()


If the enclosing scope that counter is defined in is not the global scope, on Python 3.x you could use the nonlocal statement. In the same situation on Python 2.x you would have no way to reassign to the nonlocal name counter, so you would need to make counter mutable and modify it:



counter = [0]

def increment():
counter[0] += 1

increment()
print counter[0] # prints '1'





share|improve this answer

































    14














    To answer the question in your subject line,* yes, there are closures in Python, except they only apply inside a function, and also (in Python 2.x) they are read-only; you can't re-bind the name to a different object (though if the object is mutable, you can modify its contents). In Python 3.x, you can use the nonlocal keyword to modify a closure variable.



    def incrementer():
    counter = 0
    def increment():
    nonlocal counter
    counter += 1
    return counter
    return increment

    increment = incrementer()

    increment() # 1
    increment() # 2


    * The original question's title asked about closures in Python.






    share|improve this answer

































      6














      The reason of why your code throws an UnboundLocalError is already well explained in other answers.



      But it seems to me that you're trying to build something that works like itertools.count().



      So why don't you try it out, and see if it suits your case:



      >>> from itertools import count
      >>> counter = count(0)
      >>> counter
      count(0)
      >>> next(counter)
      0
      >>> counter
      count(1)
      >>> next(counter)
      1
      >>> counter
      count(2)





      share|improve this answer































        3














        To modify a global variable inside a function, you must use the global keyword.



        When you try to do this without the line



        global counter


        inside of the definition of increment, a local variable named counter is created so as to keep you from mucking up the counter variable that the whole program may depend on.



        Note that you only need to use global when you are modifying the variable; you could read counter from within increment without the need for the global statement.






        share|improve this answer































          3














          Python has lexical scoping by default, which means that although an enclosed scope can access values in its enclosing scope, it cannot modify them (unless they're declared global with the global keyword).



          A closure binds values in the enclosing environment to names in the local environment. The local environment can then use the bound value, and even reassign that name to something else, but it can't modify the binding in the enclosing environment.



          In your case you are trying to treat counter as a local variable rather than a bound value. Note that this code, which binds the value of x assigned in the enclosing environment, works fine:



          >>> x = 1

          >>> def f():
          >>> return x

          >>> f()
          1





          share|improve this answer

































            2














            try this



            counter = 0

            def increment():
            global counter
            counter += 1

            increment()





            share|improve this answer































              0














              Python is not purely lexically scoped.



              See this: Using global variables in a function other than the one that created them



              and this: http://www.saltycrane.com/blog/2008/01/python-variable-scope-notes/






              share|improve this answer


























              • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review

                – munk
                Mar 7 '18 at 19:05











              • @munk Cool, you realise that this is a link to another answer on SO?

                – Marcin
                Mar 7 '18 at 20:33


















              8 Answers
              8






              active

              oldest

              votes








              8 Answers
              8






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              132














              Python doesn't have variable declarations, so it has to figure out the scope of variables itself. It does so by a simple rule: If there is an assignment to a variable inside a function, that variable is considered local.[1] Thus, the line



              counter += 1


              implicitly makes counter local to increment(). Trying to execute this line, though, will try to read the value of the local variable counter before it is assigned, resulting in an UnboundLocalError.[2]



              If counter is a global variable, the global keyword will help. If increment() is a local function and counter a local variable, you can use nonlocal in Python 3.x.






              share|improve this answer





















              • 5





                python 3 docs has a faq page on why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value via unboundlocalerror-local-variable-l-referenced-before-assignment-python

                – here
                May 4 '14 at 7:19













              • A note that caught me out, I had a variable declared at the top of the file that I can read inside a function without issue, however to write to a variable that I have declared at the top of the file, I had to use global.

                – mouckatron
                Feb 6 '18 at 14:35











              • A more in-depth explanation: docs.python.org/3.3/reference/…. Not only can assignments bind names, so can imports, so you may also get UnboundLocalError from a statement that uses an unbounded imported name. Example: def foo(): bar = deepcopy({'a':1}); from copy import deepcopy; return bar, then from copy import deepcopy; foo(). The call succeeds if the local import from copy import deepcopy is removed.

                – Yibo Yang
                Jun 27 '18 at 16:00


















              132














              Python doesn't have variable declarations, so it has to figure out the scope of variables itself. It does so by a simple rule: If there is an assignment to a variable inside a function, that variable is considered local.[1] Thus, the line



              counter += 1


              implicitly makes counter local to increment(). Trying to execute this line, though, will try to read the value of the local variable counter before it is assigned, resulting in an UnboundLocalError.[2]



              If counter is a global variable, the global keyword will help. If increment() is a local function and counter a local variable, you can use nonlocal in Python 3.x.






              share|improve this answer





















              • 5





                python 3 docs has a faq page on why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value via unboundlocalerror-local-variable-l-referenced-before-assignment-python

                – here
                May 4 '14 at 7:19













              • A note that caught me out, I had a variable declared at the top of the file that I can read inside a function without issue, however to write to a variable that I have declared at the top of the file, I had to use global.

                – mouckatron
                Feb 6 '18 at 14:35











              • A more in-depth explanation: docs.python.org/3.3/reference/…. Not only can assignments bind names, so can imports, so you may also get UnboundLocalError from a statement that uses an unbounded imported name. Example: def foo(): bar = deepcopy({'a':1}); from copy import deepcopy; return bar, then from copy import deepcopy; foo(). The call succeeds if the local import from copy import deepcopy is removed.

                – Yibo Yang
                Jun 27 '18 at 16:00
















              132












              132








              132







              Python doesn't have variable declarations, so it has to figure out the scope of variables itself. It does so by a simple rule: If there is an assignment to a variable inside a function, that variable is considered local.[1] Thus, the line



              counter += 1


              implicitly makes counter local to increment(). Trying to execute this line, though, will try to read the value of the local variable counter before it is assigned, resulting in an UnboundLocalError.[2]



              If counter is a global variable, the global keyword will help. If increment() is a local function and counter a local variable, you can use nonlocal in Python 3.x.






              share|improve this answer















              Python doesn't have variable declarations, so it has to figure out the scope of variables itself. It does so by a simple rule: If there is an assignment to a variable inside a function, that variable is considered local.[1] Thus, the line



              counter += 1


              implicitly makes counter local to increment(). Trying to execute this line, though, will try to read the value of the local variable counter before it is assigned, resulting in an UnboundLocalError.[2]



              If counter is a global variable, the global keyword will help. If increment() is a local function and counter a local variable, you can use nonlocal in Python 3.x.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Feb 23 '13 at 8:24









              Honest Abe

              5,45233454




              5,45233454










              answered Feb 13 '12 at 17:15









              Sven MarnachSven Marnach

              355k79754697




              355k79754697








              • 5





                python 3 docs has a faq page on why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value via unboundlocalerror-local-variable-l-referenced-before-assignment-python

                – here
                May 4 '14 at 7:19













              • A note that caught me out, I had a variable declared at the top of the file that I can read inside a function without issue, however to write to a variable that I have declared at the top of the file, I had to use global.

                – mouckatron
                Feb 6 '18 at 14:35











              • A more in-depth explanation: docs.python.org/3.3/reference/…. Not only can assignments bind names, so can imports, so you may also get UnboundLocalError from a statement that uses an unbounded imported name. Example: def foo(): bar = deepcopy({'a':1}); from copy import deepcopy; return bar, then from copy import deepcopy; foo(). The call succeeds if the local import from copy import deepcopy is removed.

                – Yibo Yang
                Jun 27 '18 at 16:00
















              • 5





                python 3 docs has a faq page on why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value via unboundlocalerror-local-variable-l-referenced-before-assignment-python

                – here
                May 4 '14 at 7:19













              • A note that caught me out, I had a variable declared at the top of the file that I can read inside a function without issue, however to write to a variable that I have declared at the top of the file, I had to use global.

                – mouckatron
                Feb 6 '18 at 14:35











              • A more in-depth explanation: docs.python.org/3.3/reference/…. Not only can assignments bind names, so can imports, so you may also get UnboundLocalError from a statement that uses an unbounded imported name. Example: def foo(): bar = deepcopy({'a':1}); from copy import deepcopy; return bar, then from copy import deepcopy; foo(). The call succeeds if the local import from copy import deepcopy is removed.

                – Yibo Yang
                Jun 27 '18 at 16:00










              5




              5





              python 3 docs has a faq page on why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value via unboundlocalerror-local-variable-l-referenced-before-assignment-python

              – here
              May 4 '14 at 7:19







              python 3 docs has a faq page on why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value via unboundlocalerror-local-variable-l-referenced-before-assignment-python

              – here
              May 4 '14 at 7:19















              A note that caught me out, I had a variable declared at the top of the file that I can read inside a function without issue, however to write to a variable that I have declared at the top of the file, I had to use global.

              – mouckatron
              Feb 6 '18 at 14:35





              A note that caught me out, I had a variable declared at the top of the file that I can read inside a function without issue, however to write to a variable that I have declared at the top of the file, I had to use global.

              – mouckatron
              Feb 6 '18 at 14:35













              A more in-depth explanation: docs.python.org/3.3/reference/…. Not only can assignments bind names, so can imports, so you may also get UnboundLocalError from a statement that uses an unbounded imported name. Example: def foo(): bar = deepcopy({'a':1}); from copy import deepcopy; return bar, then from copy import deepcopy; foo(). The call succeeds if the local import from copy import deepcopy is removed.

              – Yibo Yang
              Jun 27 '18 at 16:00







              A more in-depth explanation: docs.python.org/3.3/reference/…. Not only can assignments bind names, so can imports, so you may also get UnboundLocalError from a statement that uses an unbounded imported name. Example: def foo(): bar = deepcopy({'a':1}); from copy import deepcopy; return bar, then from copy import deepcopy; foo(). The call succeeds if the local import from copy import deepcopy is removed.

              – Yibo Yang
              Jun 27 '18 at 16:00















              68














              You need to use the global statement so that you are modifying the global variable counter, instead of a local variable:



              counter = 0

              def increment():
              global counter
              counter += 1

              increment()


              If the enclosing scope that counter is defined in is not the global scope, on Python 3.x you could use the nonlocal statement. In the same situation on Python 2.x you would have no way to reassign to the nonlocal name counter, so you would need to make counter mutable and modify it:



              counter = [0]

              def increment():
              counter[0] += 1

              increment()
              print counter[0] # prints '1'





              share|improve this answer






























                68














                You need to use the global statement so that you are modifying the global variable counter, instead of a local variable:



                counter = 0

                def increment():
                global counter
                counter += 1

                increment()


                If the enclosing scope that counter is defined in is not the global scope, on Python 3.x you could use the nonlocal statement. In the same situation on Python 2.x you would have no way to reassign to the nonlocal name counter, so you would need to make counter mutable and modify it:



                counter = [0]

                def increment():
                counter[0] += 1

                increment()
                print counter[0] # prints '1'





                share|improve this answer




























                  68












                  68








                  68







                  You need to use the global statement so that you are modifying the global variable counter, instead of a local variable:



                  counter = 0

                  def increment():
                  global counter
                  counter += 1

                  increment()


                  If the enclosing scope that counter is defined in is not the global scope, on Python 3.x you could use the nonlocal statement. In the same situation on Python 2.x you would have no way to reassign to the nonlocal name counter, so you would need to make counter mutable and modify it:



                  counter = [0]

                  def increment():
                  counter[0] += 1

                  increment()
                  print counter[0] # prints '1'





                  share|improve this answer















                  You need to use the global statement so that you are modifying the global variable counter, instead of a local variable:



                  counter = 0

                  def increment():
                  global counter
                  counter += 1

                  increment()


                  If the enclosing scope that counter is defined in is not the global scope, on Python 3.x you could use the nonlocal statement. In the same situation on Python 2.x you would have no way to reassign to the nonlocal name counter, so you would need to make counter mutable and modify it:



                  counter = [0]

                  def increment():
                  counter[0] += 1

                  increment()
                  print counter[0] # prints '1'






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Feb 13 '12 at 17:20

























                  answered Feb 13 '12 at 17:13









                  Andrew ClarkAndrew Clark

                  146k17194255




                  146k17194255























                      14














                      To answer the question in your subject line,* yes, there are closures in Python, except they only apply inside a function, and also (in Python 2.x) they are read-only; you can't re-bind the name to a different object (though if the object is mutable, you can modify its contents). In Python 3.x, you can use the nonlocal keyword to modify a closure variable.



                      def incrementer():
                      counter = 0
                      def increment():
                      nonlocal counter
                      counter += 1
                      return counter
                      return increment

                      increment = incrementer()

                      increment() # 1
                      increment() # 2


                      * The original question's title asked about closures in Python.






                      share|improve this answer






























                        14














                        To answer the question in your subject line,* yes, there are closures in Python, except they only apply inside a function, and also (in Python 2.x) they are read-only; you can't re-bind the name to a different object (though if the object is mutable, you can modify its contents). In Python 3.x, you can use the nonlocal keyword to modify a closure variable.



                        def incrementer():
                        counter = 0
                        def increment():
                        nonlocal counter
                        counter += 1
                        return counter
                        return increment

                        increment = incrementer()

                        increment() # 1
                        increment() # 2


                        * The original question's title asked about closures in Python.






                        share|improve this answer




























                          14












                          14








                          14







                          To answer the question in your subject line,* yes, there are closures in Python, except they only apply inside a function, and also (in Python 2.x) they are read-only; you can't re-bind the name to a different object (though if the object is mutable, you can modify its contents). In Python 3.x, you can use the nonlocal keyword to modify a closure variable.



                          def incrementer():
                          counter = 0
                          def increment():
                          nonlocal counter
                          counter += 1
                          return counter
                          return increment

                          increment = incrementer()

                          increment() # 1
                          increment() # 2


                          * The original question's title asked about closures in Python.






                          share|improve this answer















                          To answer the question in your subject line,* yes, there are closures in Python, except they only apply inside a function, and also (in Python 2.x) they are read-only; you can't re-bind the name to a different object (though if the object is mutable, you can modify its contents). In Python 3.x, you can use the nonlocal keyword to modify a closure variable.



                          def incrementer():
                          counter = 0
                          def increment():
                          nonlocal counter
                          counter += 1
                          return counter
                          return increment

                          increment = incrementer()

                          increment() # 1
                          increment() # 2


                          * The original question's title asked about closures in Python.







                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Apr 7 '17 at 12:08









                          Drunken Master

                          99421026




                          99421026










                          answered Feb 13 '12 at 17:21









                          kindallkindall

                          129k18194247




                          129k18194247























                              6














                              The reason of why your code throws an UnboundLocalError is already well explained in other answers.



                              But it seems to me that you're trying to build something that works like itertools.count().



                              So why don't you try it out, and see if it suits your case:



                              >>> from itertools import count
                              >>> counter = count(0)
                              >>> counter
                              count(0)
                              >>> next(counter)
                              0
                              >>> counter
                              count(1)
                              >>> next(counter)
                              1
                              >>> counter
                              count(2)





                              share|improve this answer




























                                6














                                The reason of why your code throws an UnboundLocalError is already well explained in other answers.



                                But it seems to me that you're trying to build something that works like itertools.count().



                                So why don't you try it out, and see if it suits your case:



                                >>> from itertools import count
                                >>> counter = count(0)
                                >>> counter
                                count(0)
                                >>> next(counter)
                                0
                                >>> counter
                                count(1)
                                >>> next(counter)
                                1
                                >>> counter
                                count(2)





                                share|improve this answer


























                                  6












                                  6








                                  6







                                  The reason of why your code throws an UnboundLocalError is already well explained in other answers.



                                  But it seems to me that you're trying to build something that works like itertools.count().



                                  So why don't you try it out, and see if it suits your case:



                                  >>> from itertools import count
                                  >>> counter = count(0)
                                  >>> counter
                                  count(0)
                                  >>> next(counter)
                                  0
                                  >>> counter
                                  count(1)
                                  >>> next(counter)
                                  1
                                  >>> counter
                                  count(2)





                                  share|improve this answer













                                  The reason of why your code throws an UnboundLocalError is already well explained in other answers.



                                  But it seems to me that you're trying to build something that works like itertools.count().



                                  So why don't you try it out, and see if it suits your case:



                                  >>> from itertools import count
                                  >>> counter = count(0)
                                  >>> counter
                                  count(0)
                                  >>> next(counter)
                                  0
                                  >>> counter
                                  count(1)
                                  >>> next(counter)
                                  1
                                  >>> counter
                                  count(2)






                                  share|improve this answer












                                  share|improve this answer



                                  share|improve this answer










                                  answered Feb 13 '12 at 17:31









                                  Rik PoggiRik Poggi

                                  19.5k54972




                                  19.5k54972























                                      3














                                      To modify a global variable inside a function, you must use the global keyword.



                                      When you try to do this without the line



                                      global counter


                                      inside of the definition of increment, a local variable named counter is created so as to keep you from mucking up the counter variable that the whole program may depend on.



                                      Note that you only need to use global when you are modifying the variable; you could read counter from within increment without the need for the global statement.






                                      share|improve this answer




























                                        3














                                        To modify a global variable inside a function, you must use the global keyword.



                                        When you try to do this without the line



                                        global counter


                                        inside of the definition of increment, a local variable named counter is created so as to keep you from mucking up the counter variable that the whole program may depend on.



                                        Note that you only need to use global when you are modifying the variable; you could read counter from within increment without the need for the global statement.






                                        share|improve this answer


























                                          3












                                          3








                                          3







                                          To modify a global variable inside a function, you must use the global keyword.



                                          When you try to do this without the line



                                          global counter


                                          inside of the definition of increment, a local variable named counter is created so as to keep you from mucking up the counter variable that the whole program may depend on.



                                          Note that you only need to use global when you are modifying the variable; you could read counter from within increment without the need for the global statement.






                                          share|improve this answer













                                          To modify a global variable inside a function, you must use the global keyword.



                                          When you try to do this without the line



                                          global counter


                                          inside of the definition of increment, a local variable named counter is created so as to keep you from mucking up the counter variable that the whole program may depend on.



                                          Note that you only need to use global when you are modifying the variable; you could read counter from within increment without the need for the global statement.







                                          share|improve this answer












                                          share|improve this answer



                                          share|improve this answer










                                          answered Feb 13 '12 at 17:13









                                          chucksmashchucksmash

                                          3,71811938




                                          3,71811938























                                              3














                                              Python has lexical scoping by default, which means that although an enclosed scope can access values in its enclosing scope, it cannot modify them (unless they're declared global with the global keyword).



                                              A closure binds values in the enclosing environment to names in the local environment. The local environment can then use the bound value, and even reassign that name to something else, but it can't modify the binding in the enclosing environment.



                                              In your case you are trying to treat counter as a local variable rather than a bound value. Note that this code, which binds the value of x assigned in the enclosing environment, works fine:



                                              >>> x = 1

                                              >>> def f():
                                              >>> return x

                                              >>> f()
                                              1





                                              share|improve this answer






























                                                3














                                                Python has lexical scoping by default, which means that although an enclosed scope can access values in its enclosing scope, it cannot modify them (unless they're declared global with the global keyword).



                                                A closure binds values in the enclosing environment to names in the local environment. The local environment can then use the bound value, and even reassign that name to something else, but it can't modify the binding in the enclosing environment.



                                                In your case you are trying to treat counter as a local variable rather than a bound value. Note that this code, which binds the value of x assigned in the enclosing environment, works fine:



                                                >>> x = 1

                                                >>> def f():
                                                >>> return x

                                                >>> f()
                                                1





                                                share|improve this answer




























                                                  3












                                                  3








                                                  3







                                                  Python has lexical scoping by default, which means that although an enclosed scope can access values in its enclosing scope, it cannot modify them (unless they're declared global with the global keyword).



                                                  A closure binds values in the enclosing environment to names in the local environment. The local environment can then use the bound value, and even reassign that name to something else, but it can't modify the binding in the enclosing environment.



                                                  In your case you are trying to treat counter as a local variable rather than a bound value. Note that this code, which binds the value of x assigned in the enclosing environment, works fine:



                                                  >>> x = 1

                                                  >>> def f():
                                                  >>> return x

                                                  >>> f()
                                                  1





                                                  share|improve this answer















                                                  Python has lexical scoping by default, which means that although an enclosed scope can access values in its enclosing scope, it cannot modify them (unless they're declared global with the global keyword).



                                                  A closure binds values in the enclosing environment to names in the local environment. The local environment can then use the bound value, and even reassign that name to something else, but it can't modify the binding in the enclosing environment.



                                                  In your case you are trying to treat counter as a local variable rather than a bound value. Note that this code, which binds the value of x assigned in the enclosing environment, works fine:



                                                  >>> x = 1

                                                  >>> def f():
                                                  >>> return x

                                                  >>> f()
                                                  1






                                                  share|improve this answer














                                                  share|improve this answer



                                                  share|improve this answer








                                                  edited Feb 20 '13 at 6:43









                                                  Honest Abe

                                                  5,45233454




                                                  5,45233454










                                                  answered Feb 13 '12 at 17:21









                                                  Chris TaylorChris Taylor

                                                  37.2k1196142




                                                  37.2k1196142























                                                      2














                                                      try this



                                                      counter = 0

                                                      def increment():
                                                      global counter
                                                      counter += 1

                                                      increment()





                                                      share|improve this answer




























                                                        2














                                                        try this



                                                        counter = 0

                                                        def increment():
                                                        global counter
                                                        counter += 1

                                                        increment()





                                                        share|improve this answer


























                                                          2












                                                          2








                                                          2







                                                          try this



                                                          counter = 0

                                                          def increment():
                                                          global counter
                                                          counter += 1

                                                          increment()





                                                          share|improve this answer













                                                          try this



                                                          counter = 0

                                                          def increment():
                                                          global counter
                                                          counter += 1

                                                          increment()






                                                          share|improve this answer












                                                          share|improve this answer



                                                          share|improve this answer










                                                          answered Feb 13 '12 at 17:14









                                                          LostsoulLostsoul

                                                          9,0422684141




                                                          9,0422684141























                                                              0














                                                              Python is not purely lexically scoped.



                                                              See this: Using global variables in a function other than the one that created them



                                                              and this: http://www.saltycrane.com/blog/2008/01/python-variable-scope-notes/






                                                              share|improve this answer


























                                                              • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review

                                                                – munk
                                                                Mar 7 '18 at 19:05











                                                              • @munk Cool, you realise that this is a link to another answer on SO?

                                                                – Marcin
                                                                Mar 7 '18 at 20:33
















                                                              0














                                                              Python is not purely lexically scoped.



                                                              See this: Using global variables in a function other than the one that created them



                                                              and this: http://www.saltycrane.com/blog/2008/01/python-variable-scope-notes/






                                                              share|improve this answer


























                                                              • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review

                                                                – munk
                                                                Mar 7 '18 at 19:05











                                                              • @munk Cool, you realise that this is a link to another answer on SO?

                                                                – Marcin
                                                                Mar 7 '18 at 20:33














                                                              0












                                                              0








                                                              0







                                                              Python is not purely lexically scoped.



                                                              See this: Using global variables in a function other than the one that created them



                                                              and this: http://www.saltycrane.com/blog/2008/01/python-variable-scope-notes/






                                                              share|improve this answer















                                                              Python is not purely lexically scoped.



                                                              See this: Using global variables in a function other than the one that created them



                                                              and this: http://www.saltycrane.com/blog/2008/01/python-variable-scope-notes/







                                                              share|improve this answer














                                                              share|improve this answer



                                                              share|improve this answer








                                                              edited May 23 '17 at 10:31









                                                              Community

                                                              11




                                                              11










                                                              answered Feb 13 '12 at 17:15









                                                              MarcinMarcin

                                                              35.6k1288173




                                                              35.6k1288173













                                                              • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review

                                                                – munk
                                                                Mar 7 '18 at 19:05











                                                              • @munk Cool, you realise that this is a link to another answer on SO?

                                                                – Marcin
                                                                Mar 7 '18 at 20:33



















                                                              • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review

                                                                – munk
                                                                Mar 7 '18 at 19:05











                                                              • @munk Cool, you realise that this is a link to another answer on SO?

                                                                – Marcin
                                                                Mar 7 '18 at 20:33

















                                                              While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review

                                                              – munk
                                                              Mar 7 '18 at 19:05





                                                              While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review

                                                              – munk
                                                              Mar 7 '18 at 19:05













                                                              @munk Cool, you realise that this is a link to another answer on SO?

                                                              – Marcin
                                                              Mar 7 '18 at 20:33





                                                              @munk Cool, you realise that this is a link to another answer on SO?

                                                              – Marcin
                                                              Mar 7 '18 at 20:33



                                                              Popular posts from this blog

                                                              Guess what letter conforming each word

                                                              Port of Spain

                                                              Run scheduled task as local user group (not BUILTIN)