için Python Sınıf yöntemleri nelerdir?

oy
216

Kendime Python öğretiyorum ve benim en son dersiymiş bu Python, Java değildir ve bu yüzden sadece fonksiyonları içine bütün Sınıf yöntemleri dönüm bir süre geçirdim.

Şimdi ben ile yapılır ne için Sınıf yöntemleri kullanmak gerekmez fark staticJava yöntemlerle, ama onları kullanmak ne zaman şimdi emin değilim. Bana onları sakınmak gerektiği gibi Python Sınıf yöntemleri hakkında bulabilirsiniz tüm danışma başlayanlar çizgisinde olduğunu ve standart belgelerine bunları tartışırken en opak yer almaktadır.

Herkes Sınıf yöntemleri mantıklı kullanılabilir zaman birisi bana söyleyebilir Python ya da en azından Sınıf yöntemi kullanarak iyi bir örnek var mı?

Oluştur 01/09/2008 saat 17:16
kaynak kullanıcı
Diğer dillerde...                            


16 cevaplar

oy
23

Alternatif kurucular klasik örnektir.

Cevap 01/09/2008 saat 17:27
kaynak kullanıcı

oy
158

Sınıf yöntemleri herhangi bir örneğine özgü olmayan yöntemler var, ama yine de bir şekilde sınıf dahil etmek gerektiğinde içindir. Onlar hakkında en ilginç şey onlar, alt sınıflar tarafından Java'nın statik yöntemlerle veya Python'un modül düzeyi fonksiyonları sadece mümkün olmayan bir şey geçersiz kılınabilir olmasıdır.

Eğer bir sınıf varsa MyClassve Sınıfım (fabrikada, bağımlılık enjeksiyon saplama, vs) üzerinde çalışan bir modül düzeyi işlevini bunu bir hale classmethod. Sonra alt sınıflara hazır hale gelirler.

Cevap 01/09/2008 saat 17:45
kaynak kullanıcı

oy
4

Dürüst? Ben durukyöntem veya classmethod kullanacak bir yer bulmuşsun hiç. Ben küresel işlev veya bir örnek yöntemi kullanılarak yapılamaz bir operasyon görmeye henüz ettik.

piton, Java gibi daha fazla gibi üyeler özel kullanılan ve korunan eğer farklı olurdu. Java, ben şeyler yapmak için bir örneğinin özel üye erişmek mümkün statik bir yöntem gerekir. Python'da, o nadiren gerekli.

Genellikle, onlar gerçekten yapmanız gereken tek şey için Python'un modül düzeyi ad iyi olduğunda insanlar staticmethods ve classmethods kullanarak bkz.

Cevap 01/09/2008 saat 17:54
kaynak kullanıcı

oy
60

Fabrika yöntemleri (alternatif kurucular) gerçekten de sınıf yöntemleri bir örnek teşkil etmektedir.

Temel olarak, sınıf yöntemleri her zaman doğal sınıfın ad sığar, ama sınıf belirli bir örneğiyle ilişkili olmayan bir yöntemi istiyorum uygundur.

Bir örnek olarak, mükemmel de Unipath modülü:

Güncel dizin

  • Path.cwd()
    • Gerçek şu anki dizin döndürür; örneğin Path("/tmp/my_temp_dir"). Bu sınıf yöntemidir.
  • .chdir()
    • öz geçerli dizin olun.

Geçerli dizini işlemi geniş olduğu için, cwdyöntem, ilişkili gereken ile belirli bir örneği vardır. Ancak, değişen cwdbelirli bir dizinine Pathörneğin gerçekten bir örneği yöntem olmalıdır.

Olarak Hmmm ... Path.cwd()gerçekten çıkmıyor Pathörneği, ben bir fabrika yöntemi olarak kabul edilebilir sanırım ...

Cevap 01/09/2008 saat 18:08
kaynak kullanıcı

oy
6

Ben PHP ile çalışmak için kullanılan ve son zamanlarda bu classmethod ile ne oluyor, kendime soruyordum? O alışkanlık bu özelliği anlamakta yardımcı böylece Python manuel çok teknik ve deyişle çok kısadır. Ben Googling ve googling ve cevabı bulundu -> http://code.anjanesh.net/2007/12/python-classmethods.html .

Eğer tembel değilseniz bunu tıklatın. Benim açıklamam aşağıda daha kısa ve olduğunu. :)

PHP (belki hepiniz değil PHP biliyorum ama bu dil Herkes benim bahsettiğimi anlamalıdır ki yalındır) 'de böyle statik değişkenleri vardır:


class A
{

    static protected $inner_var = null;

    static public function echoInnerVar()
    {
        echo self::$inner_var."\n";
    }

    static public function setInnerVar($v)
    {
        self::$inner_var = $v;
    }

}

class B extends A
{
}

A::setInnerVar(10);
B::setInnerVar(20);

A::echoInnerVar();
B::echoInnerVar();

Çıktı Her iki durumda 20 olacaktır.

Ancak python biz @classmethod dekoratör ekleyebilir ve böylece sırasıyla çıkışı 10 ve 20 sahip olmak mümkündür. Örnek:


class A(object):
    inner_var = 0

    @classmethod
    def setInnerVar(cls, value):
        cls.inner_var = value

    @classmethod
    def echoInnerVar(cls):
        print cls.inner_var


class B(A):
    pass


A.setInnerVar(10)
B.setInnerVar(20)

A.echoInnerVar()
B.echoInnerVar()

Akıllı, değil mi?

Cevap 22/02/2010 saat 12:27
kaynak kullanıcı

oy
26

Geçenlerde programlı kurulabileceği günlük düzeyine bağlı olarak çıkış miktarları çıkışını değişen bırakacak çok hafif günlüğü sınıfını istedi. Ama sınıf I çıkışı bir hata ayıklama mesajı veya hata veya uyarı istediği her zaman örneğini istemiyordu. Ama aynı zamanda bu günlüğü tesisin işleyişini saklanması ve herhangi globalsin beyanı olmadan yeniden kullanılabilir yapmak istedim.

Bu yüzden sınıf değişkenleri ve kullanılan @classmethodbunu başarmak için dekoratör.

Benim basit Günlüğü sınıfında, ben şu yapabilirdi:

Logger._level = Logger.DEBUG

Ben ayıklama bilgilerini bir demet tükürmek istiyorsa Sonra, benim kodda, ben sadece kod vardı

Logger.debug( "this is some annoying message I only want to see while debugging" )

Hatalar dışarı ile koymak olabilir

Logger.error( "Wow, something really awful happened." )

"Üretim" ortamında, belirtebilirim

Logger._level = Logger.ERROR

ve şimdi, sadece hata mesajı çıkışı olacaktır. ayıklama mesajı baskılı edilmeyecektir.

İşte benim sınıf var:

class Logger :
    ''' Handles logging of debugging and error messages. '''

    DEBUG = 5
    INFO  = 4
    WARN  = 3
    ERROR = 2
    FATAL = 1
    _level = DEBUG

    def __init__( self ) :
        Logger._level = Logger.DEBUG

    @classmethod
    def isLevel( cls, level ) :
        return cls._level >= level

    @classmethod
    def debug( cls, message ) :
        if cls.isLevel( Logger.DEBUG ) :
            print "DEBUG:  " + message

    @classmethod
    def info( cls, message ) :
        if cls.isLevel( Logger.INFO ) :
            print "INFO :  " + message

    @classmethod
    def warn( cls, message ) :
        if cls.isLevel( Logger.WARN ) :
            print "WARN :  " + message

    @classmethod
    def error( cls, message ) :
        if cls.isLevel( Logger.ERROR ) :
            print "ERROR:  " + message

    @classmethod
    def fatal( cls, message ) :
        if cls.isLevel( Logger.FATAL ) :
            print "FATAL:  " + message

Ve sadece biraz testleri bazı kod:

def logAll() :
    Logger.debug( "This is a Debug message." )
    Logger.info ( "This is a Info  message." )
    Logger.warn ( "This is a Warn  message." )
    Logger.error( "This is a Error message." )
    Logger.fatal( "This is a Fatal message." )

if __name__ == '__main__' :

    print "Should see all DEBUG and higher"
    Logger._level = Logger.DEBUG
    logAll()

    print "Should see all ERROR and higher"
    Logger._level = Logger.ERROR
    logAll()
Cevap 11/05/2010 saat 00:48
kaynak kullanıcı

oy
4

veya "anlamsal kolaylık" - Sınıf yöntemleri "semantik şeker" (bu terim yaygın kullanılırsa bilmiyorum) sağlarlar.

Örnek: nesneleri temsil eden sınıfları kümesi var. Sen sınıf yöntemine sahip isteyebilirsiniz all()veya find()yazmak için User.all()veya User.find(firstname='Guido'). Yani tabii modül düzeyi işlevlerini kullanarak yapılabilir ...

Cevap 17/08/2010 saat 14:53
kaynak kullanıcı

oy
44

Bu konuda bu şekilde düşünün: normal yollar sevk ayrıntılarını gizlemek için yararlıdır: Eğer yazabilirsiniz myobj.foo()olup olmadığı hakkında endişelenmeden foo()yöntemi ile uygulanan myobjnesnenin sınıf veya üst sınıflardan birinde. Sınıf yöntemleri bu tam benzeri olmakla birlikte, bunun yerine sınıf nesnesi ile: onlar diyelim MyClass.foo()olmadığı konusunda endişe duymadan foo()özel olarak yürütür MyClasskendi özel versiyonunu gerekli, yoksa kendi üst sınıf çağrıyı icar olup olmadığını çünkü.

Set-up veya hesaplama yapıyoruz zaman Sınıf yöntemleri esastır önce gelir örneği sizin yöntem çağrıları için sevk noktası olarak örneğini kullanamaz açıkçası sizi varsa kadar, çünkü gerçek bir örneğinin oluşturulmasını. Bunun iyi bir örneği SQLAlchemy kaynak kodunda izlenebilir; bakmak dbapi()şu bağlantıda sınıf yöntemiyle:

https://github.com/zzzeek/sqlalchemy/blob/ab6946769742602e40fb9ed9dde5f642885d1906/lib/sqlalchemy/dialects/mssql/pymssql.py#L47

Bunu görebilirsiniz dbapi()onu çalıştırmak gerektiğinden bir veritabanı arka uç bunu on-demand ihtiyacı satıcıya özgü veritabanı kitaplığı alma için kullandığı yöntem, bir sınıf yöntemidir önce oluşturulan dönmeye başlayabilir belirli bir veritabanı bağlantısının örnekleri - ama bu olamaz onlar benzer, üst sınıfta daha alt sınıflarda daha spesifik yazılması gerekebilir diğer destekleyici yöntemleri çağırmak mümkün olmak istiyorum, çünkü basit bir işlev veya statik işlevi olabilir. Eğer bir işlev veya statik sınıfa sevk Ve eğer, o zaman "unutmak" ve sınıf başlatılıyor hangi yapıyor hakkında bilgi kaybederler.

Cevap 19/08/2010 saat 11:51
kaynak kullanıcı

oy
10

Ben en çok net bir cevap olduğunu düşünüyorum AmanKow en biridir. Bu u kodunuzu düzenlemek istiyorum nasıl aşağı kaynar. Sen modül yani ad sarılı olan modül düzeyi işlevleri olarak herşeyi yazabilir

module.py (file 1)
---------
def f1() : pass
def f2() : pass
def f3() : pass


usage.py (file 2)
--------
from module import *
f1()
f2()
f3()
def f4():pass 
def f5():pass

usage1.py (file 3)
-------------------
from usage import f4,f5
f4()
f5()

Eğer kafa karıştırıcı alır sadece 3 modüllerin sonra görebileceğiniz gibi yukarıdaki usul kod iyi organize edilmez, her yöntem ne yapacak? Eğer kod çok hızlı yönetilemez alır ama hala (java gibi) fonksiyonları için açıklayıcı uzun adları kullanabilirsiniz.

nesne yönelimli yolu yönetilebilir bloklar Sınıfları & nesneleri yani ve işlevleri nesneler durumlarda veya sınıflar ilişkilendirilebilir içine kodunuzu yıkmak etmektir.

sınıf fonksiyonları ile modül düzeyi fonksiyonları ile karşılaştırıldığında Kodunuzdaki bölünme başka düzeyde bir artış. Yani bir sınıfın içinde grupla ilgili işlevler bu sınıfa atanmış bir göreve daha belirgin hale getirmek için olabilir. Örneğin, bir dosya yardımcı sınıf oluşturabilir:

class FileUtil ():
  def copy(source,dest):pass
  def move(source,dest):pass
  def copyDir(source,dest):pass
  def moveDir(source,dest):pass

//usage
FileUtil.copy("1.txt","2.txt")
FileUtil.moveDir("dir1","dir2")

Bu şekilde daha esnek ve daha sürdürülebilir, sen grup fonksiyonları bir arada ve her fonksiyon ne onun daha belirgin. Ayrıca kodunuzda kullandığınız (örneğin ağ kopya için) örneğin fonksiyon kopya başka ithal modülünde bulunabilir, isim çakışmalarını önlemek, böylece) tam adını FileUtil.copy (kullandığınızda sorunu ve her iki kopya işlevleri kaldırmak yan yana kullanılabilmektedir.

Cevap 14/05/2011 saat 09:24
kaynak kullanıcı

oy
8

Bir kullanıcı web sitemde giriş yaptığında bir kullanıcı () nesnesi kullanıcı adı ve şifre den örneği.

Ben giriş yapmak için orada olmanın kullanıcı olmadan bir kullanıcı nesnesi gerekiyorsa (örneğin bir yönetici kullanıcının başka kullanıcıların hesap silmek isteyebilirsiniz, bu yüzden o kullanıcıyı örneğini ve silme yöntemini çağırmak gerekir):

Ben kullanıcı nesnesini kapmak için sınıf yöntemleri var.

class User():
    #lots of code
    #...
    # more code

    @classmethod
    def get_by_username(cls, username):
        return cls.query(cls.username == username).get()

    @classmethod
    def get_by_auth_id(cls, auth_id):
        return cls.query(cls.auth_id == auth_id).get()
Cevap 26/03/2012 saat 05:36
kaynak kullanıcı

oy
2

Bu, enteresan bir konu. Üzerinde Benim alabilir piton classmethod bir singleton ziyade (bir sınıfın üretilen bir örneğini döndürür) bir fabrika gibi çalışır olmasıdır. Bir tekil olmasının sebebi ortak üretilen nesne (sözlük) ama sadece bir kez sınıf ancak paylaşımlı tüm örnekler tarafından olmasıdır.

Burada bu göstermek için bir örnektir. tüm örnekleri tek sözlüğe bir başvuru olması gerektiğini unutmayın. Anladığım kadarıyla bu fabrika kalıbı değil. Bu muhtemelen piton çok özeldir.

class M():
 @classmethod
 def m(cls, arg):
     print "arg was",  getattr(cls, "arg" , None),
     cls.arg = arg
     print "arg is" , cls.arg

 M.m(1)   # prints arg was None arg is 1
 M.m(2)   # prints arg was 1 arg is 2
 m1 = M()
 m2 = M() 
 m1.m(3)  # prints arg was 2 arg is 3  
 m2.m(4)  # prints arg was 3 arg is 4 << this breaks the factory pattern theory.
 M.m(5)   # prints arg was 4 arg is 5
Cevap 07/09/2012 saat 04:06
kaynak kullanıcı

oy
6

Bu size herhangi bir uyumlu sınıfıyla kullanabilirsiniz jenerik sınıf yöntemlerini yazmasına olanak tanır.

Örneğin:

@classmethod
def get_name(cls):
    print cls.name

class C:
    name = "tester"

C.get_name = get_name

#call it:
C.get_name()

Eğer kullanmıyorsanız @classmethodkendini anahtar kelime ile yapabilirsiniz ama Class örneğini gerekir:

def get_name(self):
    print self.name

class C:
    name = "tester"

C.get_name = get_name

#call it:
C().get_name() #<-note the its an instance of class C
Cevap 26/12/2012 saat 13:11
kaynak kullanıcı

oy
1

Ben kendime aynı soru birkaç kez soruyordu. Ve çocuklar burada anlatmaya uğraştım rağmen bulduğum en iyi cevap (ve en basit) cevap IMHO açıklama Python Dokümanlarından Sınıf yönteminin.

Statik yönteme referans bulunmaktadır. Ve birisi zaten (ı varsayalım) örnek yöntemleri bilmek durumunda, bu cevabı hep birlikte koymak için son parça olabilir ...

Dahası ve bu konuda daha derin detaylandırılması belgelerinde de bulunabilir: standart tip hiyerarşisi (aşağı kaydırarak Örnek yöntemleri bölümünde)

Cevap 14/10/2014 saat 06:07
kaynak kullanıcı

oy
0

A sınıfı elbette örneklerini bir dizi tanımlar. Ve Bağımsız örneklerde bir sınıf çalışma yöntemleri. sınıf yöntemleri (ve değişkenler) bir yerde her yerinde örnekleri setine ilişkilidir diğer bilgileri asmak için.

Örneğin sınıf sınıf değişkenleri veya öğrenci görev alabilecek sınıf seti gibi şeyler tanımlayan yöntemler isteyebilirsiniz öğrenciler bir dizi tanımlıyorsa.

Ayrıca tüm sette çalışmak için araçları tanımlamak için sınıf yöntemlerini kullanabilirsiniz. Örneğin Student.all_of_em için () bilinen tüm öğrencilerin döndürebilir. Açıkçası örneklerinin set sınıf yöntemleri bu yapısı hakkında bilmek sağlayabilir sadece bir dizi daha yapıya varsa. Students.all_of_em (derece = 'gençler')

Böyle Teknikleri sınıf değişkenleri köklü veri yapıları içine örneklerinin kümesinin üyeleri depolamak yol eğilimindedir. Daha sonra çöp toplama sinir bozucu önlemek için dikkat çekmek gerekir.

Cevap 08/09/2016 saat 00:29
kaynak kullanıcı

oy
2

Ne sadece Ruby gelen bana çarptı sözde olmasıdır sınıf yöntemi ve sözde örnek yöntemi zaman sessizce geçirilen birinci parametresi, uygulanan semantik anlam sadece bir işlevdir fonksiyonu yöntemi olarak adlandırılır bir nesne (örneğin obj.meth()).

Normal olarak bu nesne bir örneği değil olmalıdır @classmethod yöntem dekoratör bir sınıf geçmek kuralları değiştirir. Sen (bu sadece bir fonksiyon var) örneğinde bir sınıf yöntemini çağırabilirsiniz - Birinci argyment sınıfsal olacaktır.

Bu sadece bir Çünkü fonksiyon , sadece belirli bir kapsam (yani bir kez bildirilebilir classtanımı). Bir Rubyist için sürpriz olarak, bu nedenle aşağıdaki bir sınıf yöntemi ve aynı adla bir örnek yöntemini olamaz .

Bunu düşün:

class Foo():
  def foo(x):
    print(x)

Sen diyebilirsin fooÖrneğin üzerine

Foo().foo()
<__main__.Foo instance at 0x7f4dd3e3bc20>

Ama bir sınıf tarih:

Foo.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method foo() must be called with Foo instance as first argument (got nothing instead)

Şimdi eklemek @classmethod:

class Foo():
  @classmethod
  def foo(x):
    print(x)

Örneğin üzerine çağrılması artık sınıfını geçer:

Foo().foo()
__main__.Foo

Bir sınıfın çağıran yok gibidir:

Foo.foo()
__main__.Foo

Biz kullandığını dikte tek bir âdet selfbir örnek yöntemi ve bu ilk argüman için clsbir sınıf yöntemi. Bunu sadece bir argüman olduğunu göstermek için ne burada kullandı. Ruby, selfbir olduğunu anahtar kelime.

Ruby ile Kontrast:

class Foo
  def foo()
    puts "instance method #{self}"
  end
  def self.foo()
    puts "class method #{self}"
  end
end

Foo.foo()
class method Foo

Foo.new.foo()
instance method #<Foo:0x000000020fe018>

Python sınıf yöntemi sadece bir dekore fonksiyon ve aynı teknikleri kullanabilirsiniz kendi dekoratörler oluşturmak . (Durumunda bir dekore yöntem olup, gerçek bir yöntem saran @classmethodek sınıf bağımsız değişken geçer). Altta yatan yöntem hala orada, gizli ama hala erişilebilir .


dipnot: Bir sınıf ve örnek türlerinin arasına isim çatışma sonrasında bu yazdım merakımı uyandırdı. Ben çok Python uzmanından değilim ve bu herhangi yanlışsa yorumlarınızı istiyorum.

Cevap 24/03/2017 saat 18:45
kaynak kullanıcı

oy
0

@classmethodKolayca dış kaynaklardan bu sınıfın nesneleri başlatmasını için yararlı olabilir. Aşağıdakileri göz önünde bulundur:

import settings

class SomeClass:
    @classmethod
    def from_settings(cls):
        return cls(settings=settings)

    def __init__(self, settings=None):
        if settings is not None:
            self.x = settings['x']
            self.y = settings['y']

Sonra başka bir dosyada:

from some_package import SomeClass

inst = SomeClass.from_settings()

inst.x erişme ayarlarıyla aynı değeri verecektir [ 'x'].

Cevap 15/11/2019 saat 15:19
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more