modul corect de definire a variabilelor de clasă în Python [duplicate] (Programare, Python, Clasa, Atribute)

jeanc a intrebat.

Am observat că în Python, oamenii își inițializează atributele de clasă în două moduri diferite.

Primul mod este așa:

class MyClass:
  __element1 = 123
  __element2 = "this is Africa"

  def __init__(self):
    #pass or something else

Celălalt stil arată astfel::

class MyClass:
  def __init__(self):
    self.__element1 = 123
    self.__element2 = "this is Africa"

Care este modul corect de a inițializa atributele de clasă?

Comentarii

  • diferența nu este mare dacă folosiți șiruri de caractere … dar va fi cu totul altceva dacă folosiți dicte sau liste care sunt stocate prin referință –  > Por Bastian.
2 răspunsuri
juliomalegria

Niciuna dintre cele două modalități nu este neapărat corectă sau incorectă, sunt doar două tipuri diferite de elemente de clasă:

  • Elementele din afara clasei __init__ metoda sunt elemente statice; ele aparțin clasei.
  • Elementele din interiorul metodei __init__ sunt elemente ale obiectului (self); ele nu aparțin clasei.

Veți vedea mai clar acest lucru cu ajutorul unui cod:

class MyClass:
    static_elem = 123

    def __init__(self):
        self.object_elem = 456

c1 = MyClass()
c2 = MyClass()

# Initial values of both elements
>>> print c1.static_elem, c1.object_elem 
123 456
>>> print c2.static_elem, c2.object_elem
123 456

# Nothing new so far ...

# Let's try changing the static element
MyClass.static_elem = 999

>>> print c1.static_elem, c1.object_elem
999 456
>>> print c2.static_elem, c2.object_elem
999 456

# Now, let's try changing the object element
c1.object_elem = 888

>>> print c1.static_elem, c1.object_elem
999 888
>>> print c2.static_elem, c2.object_elem
999 456

După cum puteți vedea, când am schimbat elementul de clasă, acesta s-a schimbat pentru ambele obiecte. Dar, când am schimbat elementul obiect, celălalt obiect a rămas neschimbat.

Comentarii

  • dar fiind init întotdeauna executat după ce obiectul este creat, devine practic egal cu definirea variabilelor în afara obiectului init, , nu? –  > Por jeanc.
  • Dacă modificați un atribut de clasă (unul definit în afara lui __init__()) se modifică pentru întreaga clasă. Se va schimba și pentru alte instanțe, în timp ce atributele de instanță (definite în __init__()) sunt specifice fiecărei instanțe. –  > Por nitsas.
  • 67

  • Nu este în totalitate corect: static_elm se modifică pentru toate instanțele clasei atunci când sunt atribuite prin intermediul clasei (MyClass.static_element = X), așa cum se arată. Dar atunci când este atribuită prin intermediul unei instanțe de clasă, atunci, pentru acea instanță, , static_elm va deveni un membru al instanței. În cazul în care faceți acest lucru: c1.static_elem = 666, , atunci print c1.static_elem, c2.static_elem va produce 666, 999. Din interiorul clasei, self.static_elm returnează MyClass.static_elm până când se atribuie self.static_elm = X. Apoi, un nou self.static_elm este creat, ascunzând variabila de clasă (încă accesibilă prin MyClass.static_elm) –  > Por Lobotomik.
  • Lobotomik a făcut o explicație clară. Da, aceasta este o proiectare ciudată în Python, este foarte ușor de confundat cu această caracteristică proiectată în Python, deoarece elementul de clasă ar putea fi schimbat brusc pentru a fi un element de instanță. –  > Por Clock ZHONG.
  • @Lobotomik: Cred că este vorba doar de „umbrirea” variabilei de clasă, deoarece puteți accesa în continuare variabila de clasă nemodificată prin c1.__class__.static_elem. Cuvintele dvs. „static_elm va deveni un membru de instanță” sunt înțelese de mine în sensul că static_elem se va schimba din variabilă de clasă în variabilă de instanță. Nu este cazul. –  > Por gebbissimo.
James Polley

Cred că acest exemplu explică diferența dintre stiluri:

[email protected]:~$cat test.py 
#!/usr/bin/env python

class MyClass:
    element1 = "Hello"

    def __init__(self):
        self.element2 = "World"

obj = MyClass()

print dir(MyClass)
print "--"
print dir(obj)
print "--"
print obj.element1 
print obj.element2
print MyClass.element1 + " " + MyClass.element2
[email protected]:~$./test.py 
['__doc__', '__init__', '__module__', 'element1']
--
['__doc__', '__init__', '__module__', 'element1', 'element2']
--
Hello World
Hello
Traceback (most recent call last):
  File "./test.py", line 17, in <module>
    print MyClass.element2
AttributeError: class MyClass has no attribute 'element2'

element1 este legat de clasă, element2 este legat de o instanță a clasei.