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.
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.
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'
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
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
...
...
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')
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.