Python sınıfı nesneyi devralır


1243

Sınıf bildiriminin miras almasının bir nedeni var mı object?

Sadece bunu yapan bazı kodlar buldum ve neden iyi bir neden bulamıyorum.

class MyClass(object):
    # class code follows...


116
Bu sorunun cevabını (basit olsa da) bulmak oldukça zordur. "Python nesne tabanı sınıfı" veya benzerleri gibi şeyler Google'da nesne yönelimli programlama ile ilgili sayfalar ve öğretici sayfalar bulunur. Upvoting çünkü bu beni "eski ve yeni stil python nesneleri" arama terimlerine götüren ilk bağlantı
vastlysuperiorman

Yanıtlar:


763

Sınıf bildiriminin miras almasının bir nedeni var mı object?

Python 3'te, Python 2 ve 3 arasındaki uyumluluk dışında bir sebep yok . Python 2'de birçok neden var .


Python 2.x hikayesi:

Python 2.x'te (2.2'den itibaren), temel sınıf olarak varlığına veya yokluğuna bağlı olarak iki sınıf stili vardır object:

  1. "klasik" stil sınıfları: objecttemel sınıfları yoktur:

    >>> class ClassicSpam:      # no base class
    ...     pass
    >>> ClassicSpam.__bases__
    ()
  2. "yeni" stil sınıfları: temel sınıf olarak doğrudan veya dolaylı olarak (ör. yerleşik türden devralma ) object:

    >>> class NewSpam(object):           # directly inherit from object
    ...    pass
    >>> NewSpam.__bases__
    (<type 'object'>,)
    >>> class IntSpam(int):              # indirectly inherit from object...
    ...    pass
    >>> IntSpam.__bases__
    (<type 'int'>,) 
    >>> IntSpam.__bases__[0].__bases__   # ... because int inherits from object  
    (<type 'object'>,)

Kuşkusuz, bir sınıf yazarken daima yeni stil sınıflarına gitmek isteyeceksiniz. Bunu yapmanın avantajları, bazılarını listelemek için çoktur:

  • Tanımlayıcılar için destek . Özellikle, aşağıdaki yapılar tanımlayıcılarla mümkün kılınmıştır:

    1. classmethod: Sınıfı örnek yerine örtük bir bağımsız değişken olarak alan bir yöntem.
    2. staticmethod: Örtük bağımsız değişkeni selfilk bağımsız değişken olarak almayan bir yöntem .
    3. özellikleri property : Bir özniteliğin alınmasını, ayarlanmasını ve silinmesini yönetmek için işlevler oluşturun.
    4. __slots__: Bir sınıfın bellek tüketimini kaydeder ve daha hızlı öznitelik erişimi sağlar. Tabii ki, sınırlamalar getiriyor .
  • __new__Statik yöntemi: sınıf örnekleri nasıl oluşturulduğunu yeni özelleştirmenizi sağlar.

  • Yöntem çözünürlük sırası (MRO) : hangi yöntemin çağrılması gerektiğine karar verilirken bir sınıfın temel sınıfları aranır.

  • MRO ile ilgili superçağrılar . Ayrıca bkz.super() .

Eğer miras almazsan object , bunları unut. Önceki mermi noktalarının daha ayrıntılı bir açıklaması ve diğer "yeni" stil sınıflarının avantajları burada bulunabilir .

Yeni stil sınıflarının dezavantajlarından biri, sınıfın kendisinin daha fazla bellek talep etmesidir. Pek çok sınıf nesnesi oluşturmadığınız sürece, bunun bir sorun olacağından şüphe duyuyorum ve bu bir pozitif denizde batıyor.


Python 3.x hikayesi:

Python 3'te işler basitleştirilmiştir. Yalnızca yeni stil sınıfları vardır (açıkça sınıflar olarak adlandırılır), bu nedenle eklemedeki tek fark object8 karakter daha yazmanızı gerektirir. Bu:

class ClassicSpam:
    pass

tamamen aynıdır (isimlerinin dışında :-) buna:

class NewSpam(object):
     pass

ve buna:

class Spam():
    pass

Hepsi objectkendi içinde __bases__.

>>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}]
[True, True, True]

Peki ne yapmalısın?

Python 2'de: her zaman objectaçıkça . Faydaları al.

Python 3'te:object Python agnostik olmaya çalışan bir kod yazıyorsanız, yani hem Python 2'de hem de Python 3'te çalışması gerekiyorsa devralın . Aksi halde Python sizin için eklediğinden gerçekten fark etmez kamera ARKASI.


"temel sınıf olarak yerleşik bir türün varlığına veya yokluğuna bağlı olarak" => aslında "temel sınıf olarak yerleşik türün yokluğu veya varlığına" ilişkin değildir, ancak sınıfın - doğrudan veya dolaylı olarak - miras alıp almayacağı object. IIRC zaman içinde henüz yeni tip sınıflara taşınan tüm yerleşik tiplerin olmadığı bir nokta vardı.
bruno desthuilliers

@brunodesthuilliers Benim izlenimim, tüm yerleşik türlerin miras aldığı object. Etrafımda bir Python 2.2.3 var ve hızlı bir kontrolden sonra bir suçlu bulamadım, ancak daha açık hale getirmek için cevabı daha sonra yeniden yazacağım. Yine de bir örnek bulabilirseniz merakım olurdu.
Dimitris Fasarakis Hilliard

Tüm dürüstlükte (önceki yorumumda "IIRC") bu noktadan% 101 emin değilim (tüm yerleşik türlerin yeni stil sınıfları tanıtıldığında zaten yeni stil sınıflarına dönüştürülüp dönüştürülmediği) - Ben sadece sade olabilirim yanlış, ya da bu yalnızca standart lib (ancak yerleşik olmayan) türlerinden bazılarını ilgilendirmiş olabilir. Ama yine de, yeni stil sınıfının objecttemelde ne olduğunu açıklığa kavuşturmanın daha iyi olacağını düşünüyorum .
bruno desthuilliers

7
too bad stackoverflow only upvote = upvote + 1 Bu tür cevaplar için keşke yapabilsem + = N
PirateApp

1
staticmethodve classmethodeski tarz derslerde bile iyi çalışır. propertysorta eski stil sınıflarında okumak için çalışır , sadece yazma işlemlerine müdahale edemez (bu nedenle, isme atarsanız, örnek, özelliği gölgeleyen verilen adın bir niteliğini kazanır). Ayrıca, __slots__erişim hızı özelliğindeki iyileşmenin çoğunlukla yeni stil sınıfı özellik erişiminin neden olduğu zararı geri almakla ilgili olduğunu unutmayın, bu yüzden yeni stil sınıflarının bir satış noktası değildir (bellek tasarrufları bir satış noktasıdır).
ShadowRanger

540

Python 3

  • class MyClass(object): = Yeni stil sınıfı
  • class MyClass:= Yeni stil sınıfı (üstü kapalı olarak miras alınır object)

Python 2

  • class MyClass(object): = Yeni stil sınıfı
  • class MyClass:= ESKİ TARZ SINIFI

Açıklama :

Python 3.x'te temel sınıfları objecttanımlarken, tanımından bırakmanıza izin verilir . Ancak bu, izlemesi ciddi bir sorun için kapıyı açabilir ...

Python, Python 2.2'de yeni stil sınıfları tanıttı ve şimdiye kadar eski stil sınıfları gerçekten oldukça eski. Eski tarz sınıfların tartışılması 2.x belgelerine gömülür ve 3.x belgelerinde yoktur.

Sorun, Python 2.x eski stil sınıfları için sözdizimi Python 3.x yeni stil sınıfları için alternatif sözdizimi ile aynıdır . Python 2.x hala çok yaygın olarak kullanılmaktadır (örn. GAE, Web2Py) ve farkında olmadan 3.x tarzı sınıf tanımlarını 2.x koduna getiren herhangi bir kod (veya kodlayıcı) ciddi şekilde eskimiş temel nesnelerle sonuçlanacaktır. Ve eski stil sınıfları kimsenin radarında olmadığı için, onlara neyin çarptığını bilmeyeceklerdir.

Yani sadece uzun yoldan heceleyerek gözyaşları 2.x geliştirici kaydetmek.


13
"Python 3.x'te temel sınıfları tanımlarken, nesneyi tanımdan çıkarmanıza izin verilir. Ancak, bu ciddi bir sorun izlemek için kapıyı açabilir ..." Hangi sorunlardan bahsediyorsunuz?
Aidis

6
@Aidis: Sanırım hem Py2 hem de Py3 üzerinde çalışan kodun Py3'te iyi olacağını, ancak yeni stil sınıf özelliklerine dayanıyorsa Py2'de kırılacağını düşünüyorum. Şahsen, böyle bir kod yazıyorsam, açık miras atlamak ve sadece __metaclass__ = typemodülün üstüne koymak ( from __future__ import absolute_import, division, print_functionsatır :-) sonra ); Modüldeki daha sonra tanımlanmış tüm sınıfları varsayılan olarak yeni bir stil haline getiren Py2'de bir uyumluluk saldırısıdır ve Py3'te tamamen yok sayılır (sadece etrafta oturan rastgele bir global değişken), bu yüzden zararsızdır.
ShadowRanger

400

Evet, bu 'yeni bir stil' nesnesidir. Python2.2'de sunulan bir özellikti.

Yeni stil nesneler klasik nesnelere farklı bir nesne modeli var ve bazı şeyler örneği için, eski tarz nesnelerle düzgün çalışmaz super(), @propertyve tarif. Yeni bir stil sınıfının ne olduğunun iyi bir açıklaması için bu makaleye bakın .

Farkların açıklaması için SO link: Python'daki eski stil ile yeni stil sınıfları arasındaki fark nedir?


110
+1 Bunu. Eski stil sınıflarının Python 3'te gittiğine dikkat edin, bu yüzden sadece objectPython 2'den miras almanız gerekir

9
Bu gerçek bir cevap değil. sadece diğer makalelere atıfta bulunuyorum. Bence Yarin'in cevabı bu sorunun cevabı olarak kabul edilmelidir.
alwbtc

2
@alwbtc: Bu cevapta yeni bir şey var. Örneğin "super ()" ifadesinden bahsetmek beni bir başka önemli olana götürdü [ stackoverflow.com/questions/576169/… ).
ViFI

34

Python'u Zor Yoldan Öğrenin Tarihi :

Python'un bir sınıfı orijinal olarak yorumlaması birçok ciddi şekilde kırıldı. Bu hatanın farkına varıncaya kadar çok geç olmuştu ve onu desteklemek zorundaydılar. Sorunu çözmek için, "eski sınıfların" çalışmaya devam edebilmesi için bazı "yeni sınıf" stilleri gerekiyordu, ancak yeni daha doğru sürümü kullanabilirsiniz.

Bir sınıf yapmak için miras aldığınız "sınıf" olmak için küçük harfli bir "nesne" kelimesi kullanmaya karar verdiler. Kafa karıştırıcıdır, ancak bir sınıf bir sınıf yapmak için "object" adlı sınıftan miras alır, ancak bu bir nesne değildir, aslında bir sınıftır, ancak nesneden miras almayı unutmayın.

Ayrıca, yeni stil sınıfları ile eski stil sınıfları arasındaki farkın ne olduğunu bilmenizi sağlamak için, yeni stil sınıfları her zaman objectsınıftan veya miras alınan başka bir sınıftan miras alır object:

class NewStyle(object):
    pass

Başka bir örnek:

class AnotherExampleOfNewStyle(NewStyle):
    pass

Eski tarz bir temel sınıf şöyle görünürken:

class OldStyle():
    pass

Ve eski tarz bir çocuk sınıfı şöyle görünür:

class OldStyleSubclass(OldStyle):
    pass

Bir Eski Stil taban sınıfının başka bir sınıftan miras kalmadığını görebilirsiniz, ancak Eski Stil sınıfları elbette birbirinden miras alabilir. Nesneden devralma, her Python sınıfında belirli işlevlerin kullanılabilir olmasını garanti eder. Python 2.2'de yeni stil sınıfları tanıtıldı


8
Kök sınıfını çağırmak objecto kadar kafa karıştırıcı değildir ve aslında oldukça standarttır. Smalltalk adlı bir kök sınıfı Objectve adlı bir kök metasınıfı vardır Class. Neden? Çünkü, tıpkı Dogköpekler için olduğu gibi , Objectnesneler Classiçin bir sınıftır ve sınıflar için bir sınıftır. Java, C #, ObjC, Ruby ve günümüzde kök sınıfı olan insanların kullandığı sınıf tabanlı OO dillerinin çoğu Object, yalnızca Python'u değil, ad olarak bazı varyasyonları kullanır .
abarnert

30

Evet, tarihi . Onsuz, eski tarz bir sınıf yaratır.

Eğer kullanırsanız type()eski tarz nesne üzerinde, sadece "örneği" olsun. Yeni stil nesnesinde kendi sınıfını alırsınız.


Ayrıca, type()eski tarz bir sınıfta kullanıyorsanız, "type" yerine "classobj" alırsınız.
Joel Sjögren

7

Sınıf oluşturma ifadesinin sözdizimi:

class <ClassName>(superclass):
    #code follows

Özellikle miras almak istediğiniz diğer üst sınıfların yokluğunda, Python'daki tüm sınıfların kökü olan superclassher zaman olmalıdır object.

objectteknik olarak Python'daki "yeni stil" sınıflarının köküdür. Ancak bugün yeni stil sınıfları, tek sınıf tarzı olmak kadar iyidir.

Ancak, objectsınıfları oluştururken sözcüğü açıkça kullanmazsanız, diğerlerinin belirttiği gibi, Python 3.x örtük olarak objectüst sınıftan miras alır . Ama sanırım açık her zaman örtük olmaktan daha iyidir

Referans

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.