Reputation: 20856
I have the below piece of code that creates a note and adds to a notebook.
My question is more related to the global variable last_id
. When I declare it as class variable i.e. inside Class Note, I get the following error but when I declare outside the class, my code works fine.
Here are my clarifications:
last_id
, when I declare it as a global variable inside my function?Error:
C:\Python27\Basics\OOP\formytesting>python notebook.py
Traceback (most recent call last):
File "notebook.py", line 38, in <module>
firstnote = Note('This is my first memo','example')
File "notebook.py", line 10, in __init__
last_id += 1
NameError: global name 'last_id' is not defined
code.py
import datetime
last_id = 0
class Note:
def __init__(self, memo, tags):
self.memo = memo
self.tags = tags
self.creation_date = datetime.date.today()
global last_id
last_id += 1
self.id = last_id
#global last_id
#last_id += 1
#self.id = last_id
def __str__(self):
return 'Memo={0}, Tag={1}, id={2}'.format(self.memo, self.tags,self.id)
class NoteBook:
def __init__(self):
self.notes = []
def add_note(self,memo,tags):
self.notes.append(Note(memo,tags))
def __iter__(self):
for note in self.notes:
yield note
if __name__ == "__main__":
firstnote = Note('This is my first memo','example')
print(firstnote)
Notes = NoteBook()
print("Adding a new note object")
Notes.add_note('Added thru notes','example-1')
Notes.add_note('Added thru notes','example-2')
for note in Notes.notes:
print(note.memo,note.tags)
for note in Notes:
print(note)
print("Adding a new note object----End")
Upvotes: 7
Views: 51799
Reputation: 3911
When you write
global last_id
Inside your function, you are not creating a new global variable. What you are doing is saying "instead of creating a new local variable and associating it to the name last_id
, instead associate that name to a pre-existing variable in the enclosing scope that has the name last_id
"
If there is not already a variable called last_id
, then global last_id
doesn't refer to anything until you write to it. However if you write to it, it will be created in the global scope. For example:
>>> def x():
... global X
... X = 1
...
>>> x()
# No error
>>> X
1 # X is now defined
>>> def y():
... global Y
... print Y
...
>>> y()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in y
NameError: global name 'Y' is not defined
Upvotes: 10
Reputation: 156128
python is a bit more explicit about where attributes come from than other object oriented languages; you can have a class level counter, like so:
from itertools import count
class Foo(object):
last_id = count()
def __init__(self):
self.id = self.last_id.next()
you must refer to last_id
as self.last_id
, so that python knows to look on the instance (and since it's not already there, the class).
Upvotes: 9
Reputation: 13289
Python uses the variable's inner-most scope, so this
def __init__(self, memo, tags):
....
global last_id
last_id += 1
will work but this
def __init__(self, memo, tags):
....
last_id += 1
will not.
You could rewrite it as
class Note:
last_id = 0;
def __init__(self, memo, tags):
self.memo = memo
self.tags = tags
self.creation_date = datetime.date.today()
Note.last_id += 1
self.id = last_id
Upvotes: 0
Reputation: 798436
The global
statement doesn't bind a name, it merely tells the compiler that the variable should be rebound in global scope when it happens. You must still perform the initial bind yourself.
Upvotes: 2