Python'daki sınıf yöntemleri içindeki “statik” sınıf değişkenlerine nasıl erişebilirim?


Yanıtlar:


166

Yerine barkullanımı self.barveya Foo.bar. Olarak atamak Foo.barstatik bir değişken yaratır ve atamak self.barbir örnek değişkeni oluşturur.


12
Foo.bar çalışır, ancak self.bar statik olmayan bir örnek değişken oluşturur.
bedwyr

47
bedwyr, "print self.bar" herhangi bir örnek değişkeni oluşturmaz (self.bar öğesine atanmasına rağmen).
Constantin

@Constantin - Bunun farkında değildim, ilginç bir ayrım. Düzeltme için teşekkürler :-)
bedwyr

2
Ancak bir ivar olmasını istemiyorsanız, Foo.classmember'i kullanmak daha açıktır.
mk12

2
statik değişkenleri kullanırken, gotchas'ı buradan okumak iyi bir fikirdir: stackoverflow.com/questions/68645/… . @Canstantin birçok yakadan birini verir.
Trevor Boyd Smith

84

Sınıf yöntemini tanımlayın:

class Foo(object):
    bar = 1
    @classmethod
    def bah(cls):    
        print cls.bar

Şimdi bah()örnek yöntemi olması gerekiyorsa (yani kendine erişebiliyorsanız), yine de sınıf değişkenine doğrudan erişebilirsiniz.

class Foo(object):
    bar = 1
    def bah(self):    
        print self.bar

3
Neden self.__class__.bar yerine sadece Foo.bar değil?
mk12

15
@ Mk12: Sınıf mirasınız olduğunda, "sınıf değişkeni" temel sınıfta veya alt sınıfta olabilir. Hangisine başvurmak istersiniz? Ne yapmaya çalıştığınıza bağlı. Foo.bar her zaman belirtilen sınıfın temel sınıf veya alt sınıf olabilen bir niteliğini belirtir. self.__class__.bar, örneğin hangi sınıfta olduğunu belirtir.
Craig McQueen

7
Şimdi, dilin ayrıntılarının farkında olduğumuzda, iki ince ayarlı kullanım durumu arasında ayrım yapabileceğimiz talihsiz bir noktaya geldik. Gerçekten ne yapmak istediğinize bağlı, ancak birçok insan bu inceliklere katılmayacak.
holdenweb

2
BTW, bu "sınıf değişkeni" NADİR kullanımıdır. Belirli bir sınıfta tanımlanması çok daha yaygın, burada Foo. Bu, bazı gelişmiş programlama durumları için yararlı bilgilerdir. Ama neredeyse kesin olarak asıl sorunun bir cevap olarak ne istediğini (BU cevaba ihtiyacı olan herkes Foo.bar'ın nasıl yapılacağını zaten bilecektir). +1 çünkü bundan bir şey öğrendim.
ToolmakerSteve

3
Ne zaman sınıf değişkenleri ve yöntemleri (örnek değişkenleri ve yöntemleri aksine) kullanılacağını öğreniyorum. Bir örnek yönteminde bir sınıf değişkenine erişmek istediğinizde self.__class__.bar kullanmak gerekir mi? Ben bar bir örnek değişken değil bir sınıf değişkeni olmasına rağmen self.bar çalışır fark ettim.
Bill

13

Tüm iyi örneklerde olduğu gibi, aslında yapmaya çalıştığınız şeyi basitleştirdiniz. Bu iyidir, ancak sınıf ve örnek değişkenleri söz konusu olduğunda python'un çok fazla esnekliğe sahip olduğunu belirtmek gerekir . Aynı şey yöntemler için de söylenebilir. Olasılıkların iyi bir listesi için, Michael Fötsch'in yeni stil sınıfları tanıtımını , özellikle 2'den 6'ya kadar olan bölümleri okumanızı tavsiye ederim .

Başlarken hatırlanması gereken çok şey gerektiren bir şey, python'un java olmamasıdır. Bir klişeden daha fazlası. Java'da, tüm sınıf derlenir ve ad alanı çözünürlüğünü basitleştirir: bir yöntemin dışında (herhangi bir yerde) bildirilen değişkenler örnek (veya statik ise sınıf) değişkenleridir ve yöntemler içinde dolaylı olarak erişilebilir.

Python ile, genel kural, değişkenler için sırayla aranan üç ad alanının olmasıdır:

  1. İşlev / yöntem
  2. Mevcut modül
  3. yerleşikleri

{begin pedagogy}

Bunun sınırlı istisnaları vardır. Benim için esas olan, bir sınıf tanımı yüklenirken, sınıf tanımının kendi örtük ad alanı olmasıdır. Ancak bu sadece modül yüklendiği sürece devam eder ve bir yöntem içindeyken tamamen atlanır. Böylece:

>>> class A(object):
        foo = 'foo'
        bar = foo


>>> A.foo
'foo'
>>> A.bar
'foo'

fakat:

>>> class B(object):
        foo = 'foo'
        def get_foo():
            return foo
        bar = get_foo()



Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    class B(object):
  File "<pyshell#11>", line 5, in B
    bar = get_foo()
  File "<pyshell#11>", line 4, in get_foo
    return foo
NameError: global name 'foo' is not defined

{end pedagogy}

Sonunda, hatırlamak şey olduğunu do muhtemelen örtülü erişmek istediğiniz değişkenlerin herhangi erişebilir, ama. Hedefleriniz basit ve anlaşılırsa, Foo.bar veya self.bar'a gitmek muhtemelen yeterli olacaktır. Örneğiniz daha karmaşık hale geliyorsa veya kalıtım gibi süslü şeyler yapmak istiyorsanız (statik / sınıf yöntemlerini miras alabilirsiniz!) Veya sınıfın kendisinin sınıf içindeki ismine gönderme fikri sizin için yanlış görünüyor, kontrol edin bağlandığım giriş.


IIRC'de, teknik olarak 3 (+) ad alanı aranır - fonksiyon-yerel, modül / global ve yerleşikler. İç içe kapsamlar, birden çok yerel kapsamın aranabileceği anlamına gelir, ancak bu istisnai durumlardan biridir. (...)
Jeff Shannon

Ayrıca, 'ana modül' demeye dikkat ediyorum, çünkü fonksiyonun ana modülü değil, aranan modülü içeriyor ... Ve bir örnek ref'den özniteliğe bakmak farklı bir şey, ama bu cevap nedenini açıklıyor örneğe / sınıfa ihtiyacınız var ref.
Jeff Shannon


-2
class Foo(object):    
    bar = 1

    def bah(object_reference):
        object_reference.var = Foo.bar
        return object_reference.var


f = Foo() 
print 'var=', f.bah()

4
Bu kod, sorunun nasıl ve neden çözüldüğüne dair bir açıklama da dahil olmak üzere soruyu çözebilir, ancak gönderinizin kalitesini artırmaya yardımcı olabilir ve muhtemelen daha fazla oyla sonuçlanır. Sadece şimdi soran kişi için değil, gelecekte okuyucular için soruyu cevapladığınızı unutmayın. Lütfen açıklama eklemek için cevabınızı düzenleyin ve hangi sınırlamaların ve varsayımların geçerli olduğunu belirtin. Yorumdan
double-beep
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.