web-dev-qa-db-fra.com

différence entre les variables à l'intérieur et à l'extérieur de __init __ ()

Existe-t-il une différence entre ces classes en plus du nom?

class WithClass ():
    def __init__(self):
        self.value = "Bob"
    def my_func(self):
        print(self.value)

class WithoutClass ():
    value = "Bob"

    def my_func(self):
        print(self.value)

Est-ce que cela fait une différence si j'utilise ou non le __init__ méthode pour déclarer la variable value?

Mon souci principal est que je l'utilise d'une manière, lorsque cela me causera d'autres problèmes plus tard.

167
Teifion

Ensemble variable en dehors de __init__ appartient à la classe. Ils sont partagés par toutes les instances.

Variables créées à l'intérieur de __init__ (et toutes les autres fonctions de méthode) et précédé de self. appartiennent à l'instance d'objet.

204
S.Lott

sans moi

Créer des objets:

class foo(object):
    x = 'original class'

c1, c2 = foo(), foo()

Je peux changer l'instance c1 et cela n'affectera pas l'instance c2:

c1.x = 'changed instance'
c2.x
>>> 'original class'

Mais si je change de classe foo, toutes les instances de cette classe seront également modifiées:

foo.x = 'changed class'
c2.x
>>> 'changed class'

Veuillez noter comment Python fonctionne ici:

c1.x
>>> 'changed instance'

avec soi

Changer la classe n'affecte pas les instances:

class foo(object):
    def __init__(self):
        self.x = 'original self'

c1 = foo()
foo.x = 'changed class'
c1.x
>>> 'original self'
70
northben

Je voudrais ajouter quelque chose aux réponses que j'ai lues dans ce fil et ce fil (qui fait référence à celui-ci).

Disclaimer : ces remarques viennent des expériences que j'ai menées

Variables hors __init__:

Ce sont en fait variables de classe statiques et sont donc accessibles à toutes les instances de la classe.

Variables à l'intérieur de __init__:

La valeur de ces variables d’instance ne sont accessibles qu’à l’instance en question (via la référence self

Ma contribution :

Une chose que les programmeurs doivent prendre en compte lors de l'utilisation de variables de classe statiques est qu'ils peuvent être masqués par variables d'instance (si vous accédez à la classe statique variables via la référence self).

Explication :

Auparavant, je pensais que les deux manières de déclarer les variables étaient exactement les mêmes (idiot moi), et c'était en partie parce que je pouvais accéder aux deux types de variables via la référence self. C’est maintenant que, lorsque j’ai eu des problèmes, j’ai étudié le sujet et l’a éclairci.

Le problème avec l’accès à variables de classe statiques via la référence self est qu’il fait uniquement référence à la variable de classe statique s’il n’existe pas instance variable avec le même nom, et pour aggraver les choses, essayer de redéfinir a variable de classe statique via la référence self ne fonctionne pas car un = variable d'instance est créé et masque ensuite la variable précédemment accessible variable de classe statique.

Pour résoudre ce problème, vous devez toujours faire référence à variables de classe statiques via le nom de la classe.

Exemple :

#!/usr/bin/env python

class Foo:
    static_var = 'every instance has access'

    def __init__(self,name):
        self.instance_var = 'I am %s' % name

    def printAll(self):
        print 'self.instance_var = %s' % self.instance_var
        print 'self.static_var = %s' % self.static_var
        print 'Foo.static_var = %s' % Foo.static_var

f1 = Foo('f1')

f1.printAll()

f1.static_var = 'Shadowing static_var'

f1.printAll()

f2 = Foo('f2')

f2.printAll()

Foo.static_var = 'modified class'

f1.printAll()
f2.printAll()

Sortie :

self.instance_var = I am f1
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = every instance has access
self.instance_var = I am f2
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = modified class
self.instance_var = I am f2
self.static_var = modified class
Foo.static_var = modified class

J'espère que cela est utile à quelqu'un

12
alejandro

suite à la réponse de S.Lott, les variables de classe sont transmises à la méthode metaclass new et sont accessibles via le dictionnaire lorsqu'une métaclasse est définie. Ainsi, les variables de classe peuvent être consultées avant même que les classes ne soient créées et instanciées.

par exemple:

class meta(type):
    def __new__(cls,name,bases,dicto):
          # two chars missing in original of next line ...
          if dicto['class_var'] == 'A':
             print 'There'
class proxyclass(object):
      class_var = 'A'
      __metaclass__ = meta
      ...
      ...
5
Neil
class User(object):
    email = 'none'
    firstname = 'none'
    lastname = 'none'

    def __init__(self, email=None, firstname=None, lastname=None):
        self.email = email
        self.firstname = firstname
        self.lastname = lastname

    @classmethod
    def print_var(cls, obj):
        print ("obj.email obj.firstname obj.lastname")
        print(obj.email, obj.firstname, obj.lastname)
        print("cls.email cls.firstname cls.lastname")
        print(cls.email, cls.firstname, cls.lastname)

u1 = User(email='abc@xyz', firstname='first', lastname='last')
User.print_var(u1)

Dans le code ci-dessus, la classe User a 3 variables globales, chacune avec la valeur 'none'. u1 est l'objet créé en instanciant cette classe. La méthode print_var affiche la valeur des variables de classe de la classe User et des variables d'objet de l'objet u1. Dans le résultat ci-dessous, chacune des variables de classe User.email, User.firstname et User.lastname a la valeur 'none', tandis que les variables d'objet u1.email, u1.firstname et u1.lastname ont des valeurs 'abc@xyz', 'first' et 'last'.

obj.email obj.firstname obj.lastname
('abc@xyz', 'first', 'last')
cls.email cls.firstname cls.lastname
('none', 'none', 'none')
1
Chaitanya Vardhan

C'est très facile à comprendre si vous suivez les dictionnaires de classes et d'instances.

class C:
   one = 42
   def __init__(self,val):
        self.two=val
ci=C(50)
print(ci.__dict__)
print(C.__dict__)

Le résultat sera comme ça:

{'two': 50}
{'__module__': '__main__', 'one': 42, '__init__': <function C.__init__ at 0x00000213069BF6A8>, '__dict__': <attribute '__dict__' of 'C' objects>, '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None}

Notez que je mets tous les résultats ici, mais il est important que l'instance ci dict soit simplement {'two': 50}, et le dictionnaire de classe aura le 'one': 42 paire de valeurs de clé à l'intérieur.

C'est tout ce que vous devez savoir sur ces variables spécifiques.

0
prosti