Don't understand why UnboundLocalError occurs [duplicate]












118















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.











  • 31




    @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






  • 6




    @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
















118















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.











  • 31




    @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






  • 6




    @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














118












118








118


32






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

65.9k989177




65.9k989177










asked Feb 13 '12 at 17:11









Randomblue

35.1k117283501




35.1k117283501




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.










  • 31




    @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






  • 6




    @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














  • 31




    @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






  • 6




    @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








31




31




@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




6




6




@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


















127














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































    13














    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









              127














              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


















              127














              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
















              127












              127








              127






              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,26933254




              5,26933254










              answered Feb 13 '12 at 17:15









              Sven Marnach

              344k77741695




              344k77741695








              • 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 Clark

                  143k17188251




                  143k17188251























                      13














                      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




























                        13














                        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


























                          13












                          13








                          13






                          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

                          9392825




                          9392825










                          answered Feb 13 '12 at 17:21









                          kindall

                          127k17192241




                          127k17192241























                              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 Poggi

                                  19k54872




                                  19k54872























                                      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









                                          chucksmash

                                          3,58811938




                                          3,58811938























                                              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,26933254




                                                  5,26933254










                                                  answered Feb 13 '12 at 17:21









                                                  Chris Taylor

                                                  37k1195141




                                                  37k1195141























                                                      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









                                                          Lostsoul

                                                          8,8992682139




                                                          8,8992682139























                                                              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









                                                              Marcin

                                                              35.1k1188171




                                                              35.1k1188171












                                                              • 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

                                                              Costa Masnaga

                                                              Fotorealismo

                                                              Sidney Franklin