@Classmethod ve def method (self) ne zaman kullanmalıyım?


92

Daha önce kullanmadığım bir Django uygulamasını entegre ederken, sınıflarda işlevleri tanımlamak için kullanılan iki farklı yol buldum. Yazar ikisini de çok isteyerek kullanıyor gibi görünüyor. İlki benim çok kullandığım şey:

class Dummy(object):

    def some_function(self,*args,**kwargs):
        do something here
        self is the class instance

Diğeri ise kullanmadığım, çoğunlukla ne zaman kullanacağımı ve ne için kullanacağımı anlamadığım için:

class Dummy(object):

    @classmethod
    def some_function(cls,*args,**kwargs):
        do something here
        cls refers to what?

Python belgelerinde, classmethoddekoratör şu cümleyle açıklanmıştır:

Bir sınıf yöntemi, bir örnek yönteminin örneği aldığı gibi, sınıfı örtük ilk bağımsız değişken olarak alır.

Bu yüzden sanırım kendine clsatıfta bulunuyor Dummy( classörneğe değil). Bunun neden var olduğunu tam olarak anlamıyorum, çünkü bunu her zaman yapabilirim:

type(self).do_something_with_the_class

Bu sadece açıklık olsun diye mi yoksa en önemli kısmı mı kaçırdım: onsuz yapılamayacak ürkütücü ve büyüleyici şeyler?

Yanıtlar:


71

Tahminin doğru - nasıl classmethod çalıştığını anlıyorsun .

Bunun nedeni, bu yöntemlerin hem sınıfta OR örneğinde VEYA çağrılabilmesidir (her iki durumda da, sınıf nesnesi ilk argüman olarak iletilecektir):

class Dummy(object):

    @classmethod
    def some_function(cls,*args,**kwargs):
        print cls

#both of these will have exactly the same effect
Dummy.some_function()
Dummy().some_function()

Bunların örneklerde kullanımı hakkında : Bir örnekte sınıf yöntemini çağırmanın en az iki ana kullanımı vardır:

  1. self.some_function()o çağrının göründüğü sınıf yerine some_functiongerçek türündeki sürümünü selfçağırır (ve sınıf yeniden adlandırılırsa ilgilenilmesi gerekmez); ve
  2. some_functionBazı protokollerin uygulanmasının gerekli olduğu, ancak yalnızca sınıf nesnesini çağırmanın yararlı olduğu durumlarda .

Aradaki farkstaticmethod : Örnek verisine erişmeyen yöntemleri tanımlamanın başka bir yolu vardır staticmethod. Bu, hiçbir şekilde örtük bir ilk argüman almayan bir yöntem yaratır; buna göre çağrıldığı örnek veya sınıf hakkında herhangi bir bilgi aktarılmayacaktır.

In [6]: class Foo(object): some_static = staticmethod(lambda x: x+1)

In [7]: Foo.some_static(1)
Out[7]: 2

In [8]: Foo().some_static(1)
Out[8]: 2

In [9]: class Bar(Foo): some_static = staticmethod(lambda x: x*2)

In [10]: Bar.some_static(1)
Out[10]: 2

In [11]: Bar().some_static(1)
Out[11]: 2

Bunun için bulduğum ana kullanım, mevcut bir işlevi (a almayı beklemeyen self) bir sınıf (veya nesne) üzerinde bir yöntem olacak şekilde uyarlamaktır .


2
Güzel cevap: Cevabın nasıl - neden şeklinde bölünmesini seviyorum. Aldığım kadarıyla @ classmethod, bir örneğe ihtiyaç duymadan işleve erişmeye izin veriyor. Bu tam olarak aradığım şey, teşekkür ederim.
04'te marue

1
@marcin Gerçek ördek yazımı ona başka bir boyut katıyor. Daha çok self.foo(), olması gerektiği gibi şeyler yazmamakla ilgiliydi Bar.foo().
Voo

5
@Voo Aslında self.foo()tercih edilir, çünkü selfkendi alt sınıfının bir örneği olabilir foo.
Marcin

1
@Marcin Bence bu, neye ulaşmak istediğinize bağlı. Ama ne demek istediğini anladım.
Marue

1
Sen için farklı lamda kullanmalısınız Barolarak, 1+1 == 2 == 1*2bu gösterilen sonuçlardan söylemek imkansız, bu yüzden Bar().static_methodaslında denir.
George V. Reilly

0

Temel olarak, yöntemin tanımının değiştirilmeyeceğini veya geçersiz kılınmayacağını anladığınızda @ classmethod kullanmalısınız.

Ek olarak: teorik olarak, sınıf yöntemleri nesne yöntemlerinden daha hızlıdır çünkü somutlaştırılması gerekmez ve daha az belleğe ihtiyaç duyar.


-3

Dekoratör @classmethod eklerseniz, bu, bu yöntemi java veya C ++ 'nın statik yöntemi olarak yapacağınız anlamına gelir. (statik yöntem sanırım genel bir terimdir ;) ) Python ayrıca @staticmethod'a da sahiptir. ve sınıf yöntemi ile statik yöntem arasındaki fark, sınıfa veya statik değişkene bağımsız değişken veya sınıf adının kendisini kullanarak erişip erişemeyeceğinizdir.

class TestMethod(object):
    cls_var = 1
    @classmethod
    def class_method(cls):
        cls.cls_var += 1
        print cls.cls_var

    @staticmethod
    def static_method():
        TestMethod.cls_var += 1
        print TestMethod.cls_var
#call each method from class itself.
TestMethod.class_method()
TestMethod.static_method()

#construct instances
testMethodInst1 = TestMethod()    
testMethodInst2 = TestMethod()   

#call each method from instances
testMethodInst1.class_method()
testMethodInst2.static_method()

tüm bu sınıflar cls.cls_var değerini 1 artırır ve yazdırır.

Ve bu sınıfla oluşturulan aynı kapsamda veya örneklerde aynı adı kullanan her sınıf, bu yöntemleri paylaşacaktır. Yalnızca bir TestMethod.cls_var ve ayrıca yalnızca bir TestMethod.class_method (), TestMethod.static_method () var

Ve önemli soru. neden bu yönteme ihtiyaç duyulacağı.

classmethod veya staticmethod, bu sınıfı fabrika olarak yaptığınızda veya sınıfınızı yalnızca bir kez başlatmanız gerektiğinde kullanışlıdır. dosyayı bir kez açmak ve dosyayı satır satır okumak için besleme yöntemini kullanmak gibi.


2
(a) Statik yöntemler başka bir şeydir; (b) sınıf yöntemleri her sınıf tarafından paylaşılmaz.
Marcin

@Marcin, net olmayan tanımlarımı falan bilmeme izin verdiğin için teşekkürler.
Ryan Kim
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.