web-dev-qa-db-fra.com

Déclaration de variable globale Python

J'ai le code ci-dessous qui crée une note et l'ajoute à un cahier.

Ma question concerne davantage la variable globale last_id. Lorsque je le déclare en tant que variable de classe, c'est-à-dire dans Class Note, j'obtiens le message d'erreur suivant, mais lorsque je déclare en dehors de la classe, mon code fonctionne correctement.

Voici mes clarifications:

  1. Pourquoi n'accepte-t-il pas la variable de classe?.
  2. Pourquoi ai-je besoin de définir last_id lorsque je le déclare en tant que variable globale dans ma fonction?

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 __== "__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")    
7
user1050619

Quand tu écris

global last_id

Dans votre fonction, vous ne créez pas de nouvelle variable globale. Vous dites "au lieu de créer une nouvelle variable locale et de l'associer au nom last_id, associez plutôt ce nom à une variable préexistante de l'étendue englobante qui porte le nom last_id"

S'il n'y a pas déjà une variable appelée last_id, alors global last_id ne fait référence à rien avant que vous n'y écriviez. Cependant, si vous y écrivez, il sera créé dans la portée globale. Par exemple:

>>> 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
10
Gordon Bailey

python est un peu plus explicite sur l'origine des attributs que d'autres langages orientés objet. vous pouvez avoir un compteur de niveau de classe, comme ceci:

from itertools import count

class Foo(object):
    last_id = count()

    def __init__(self):
        self.id = self.last_id.next()

vous devez faire référence à last_id en tant que self.last_id, afin que python sache regarder sur l'instance (et puisqu'elle n'est pas déjà présente, la classe).

L'instruction global ne lie pas un nom, elle indique simplement au compilateur que la variable doit être rebondie dans la portée globale lorsque cela se produit. Vous devez toujours effectuer la liaison initiale vous-même.

2

Python utilise la portée la plus interne de la variable, donc ceci

def __init__(self, memo, tags):
     ....
    global last_id
    last_id += 1

travaillera mais cela

def __init__(self, memo, tags):
     ....
    last_id += 1

ne sera pas.

Vous pouvez le réécrire comme

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
0
dfb