J'utilise Python rarement, donc je ne comprends pas pourquoi un tel comportement est autorisé: Il n'y a pas d'objet w et donc il n'a pas d'attribut s, alors pourquoi f permet de faire une affectation w.s?

>>> def f():
    w.s="ads"  #allows, no exception
>>> w.s="sds"  #outside function
Traceback (most recent call last):
  File "<pyshell#74>", line 1, in <module>
    w.s="sds"
NameError: name 'w' is not defined
2
parsecer 7 août 2016 à 07:42

3 réponses

Meilleure réponse

Un tel comportement est autorisé car Python est un langage dynamique. Au moment de la compilation, lorsque la définition de la fonction f est exécutée (c'est-à-dire compilée en code octet), l'interpréteur sait qu'il n'y a aucun objet local dans la fonction lié au nom w, donc {{X2 }} doit faire référence à un objet global. Bien sûr, il n'y a actuellement aucun objet dans la portée globale qui est lié à ce nom, mais cela n'a pas d'importance: Python suppose que vous savez ce que vous faites, jusqu'à preuve du contraire :).

Nous pouvons utiliser le module dis pour désassembler le code d'octet de la fonction. Voici une courte démo.

from dis import dis

def f():
    w.s = "ads"

dis(f)
print('- ' * 30)

class Test(object):
    pass

try:
    f()
except Exception as e:
    print(e)

w = Test()
f()
print(w.__dict__)

sortie

 40           0 LOAD_CONST               1 ('ads')
              3 LOAD_GLOBAL              0 (w)
              6 STORE_ATTR               1 (s)
              9 LOAD_CONST               0 (None)
             12 RETURN_VALUE
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
name 'w' is not defined
{'s': 'ads'}

FWIW, en Python 2, le code d'octet pour f est identique, mais le message d'erreur NameException est
global name 'w' is not defined.

Donc, si nous essayons d'appeler f() sans w valide dans la portée globale au moment de l'appel, nous obtiendrons une exception, mais s'il y a _is _ un w valide, alors tout va bien .

Notez que w doit être dans la portée globale, un w local dans une autre fonction ne fonctionnera pas. Par exemple:

def f():
    w.s = "ads"

class Test(object):
    pass

def g():
    w = Test()
    try:
        f()
    except Exception as e:
        print(e)
    print(w.__dict__)

g()

sortie

name 'w' is not defined
{}
2
PM 2Ring 7 août 2016 à 07:52

Essayez d'exécuter votre fonction et voyez ce qui se passe. Python ne l'attrape pas lorsque vous écrivez votre code, mais dès que vous l'exécuterez, il affichera une erreur.

Ce que vous voyez, c'est que python ne sait pas qu'au moment où votre fonction s'exécute, il n'y aura pas d'objet w avec un attribut s. Cependant, lorsque vous le faites en dehors de l'appel de fonction, il vérifie qu'il n'y a pas w dans la portée et donc des erreurs.

Essaye ça:

def f():
    w.s = "one"
w.s  = "one" # called before there is such an object
f() # called before w exists, it will error out    

class SomeClass(object):
    def __init__(self):
        self.s = "two"

w = SomeClass()
f() # since w exists it will run
5
limbo 7 août 2016 à 05:42

Une fonction n'est pas encore en cours d'exécution car elle n'a pas encore été appelée, contrairement à l'affectation de w.s à "sds" en dehors de la fonction.

4
Abhi V 7 août 2016 à 04:46