Tüm Python sınıfları nesneyi genişletmeli mi?


129

Aşağıdaki her ikisinin de işe yaradığını buldum:

class Foo():
    def a(self):
        print "hello"

class Foo(object):
    def a(self):
        print "hello"

Tüm Python sınıfları nesneyi genişletmeli mi? Nesneyi genişletmeme ile ilgili olası sorunlar var mı?


2
Arasında bir fark var mı class Foo():ve class Foo:? Gözlemlediğim gibi, ikisi de Python 3'te çalışıyor.
Wolf

Bu soruya iyi cevap verildi: stackoverflow.com/questions/4015417/…
nngeek

Yanıtlar:


117

Python 2'de, ondan miras almamak object, diğer etkilerin yanı sıra typefarklı sonuçlar vermesine neden olan eski tarz bir sınıf oluşturacaktır :

>>> class Foo: pass
... 
>>> type(Foo())
<type 'instance'>

vs.

>>> class Bar(object): pass
... 
>>> type(Bar())
<class '__main__.Bar'>

Ayrıca çoklu miras kuralları, burada özetlemeye bile çalışmayacağım yönlerden farklıdır . MI hakkında gördüğüm tüm iyi belgeler, yeni tarz sınıfları tanımlar.

Son olarak, eski tarz sınıflar Python 3'te kayboldu ve kalıtım objectörtük hale geldi. Bu nedenle, eski yazılımla geriye dönük uyumluluğa ihtiyacınız olmadıkça her zaman yeni stil sınıflarını tercih edin.


68

Python 3'te sınıflar object, kendiniz söyleseniz de söylemeseniz de örtük olarak genişler .

Python 2'de eski tarz ve yeni tarz sınıflar var. Bir sınıfın yeni stil olduğunu belirtmek için, açıkça miras almalısınız object. Değilse, eski tarz uygulama kullanılır.

Genelde yeni tarzda bir sınıf istiyorsunuz. Açık olarak devralın object. Bunun, Python 2 ile uyumlu olmayı amaçlayan Python 3 kodu için de geçerli olduğunu unutmayın.



4
Foo (object): kullanan çok sayıda python 3 kodu vardır :. Bu sadece bir kongre mi?
RFV5s

2
@RFVenter Hem Python 2 hem de 3 altında çalışması gereken kod olabilir, bu durumda sınıfın Python 2 altında büyük ölçüde aynı şekilde davranmasını sağlamak için açıkça nesneyi alt sınıflara
ayırmanız gerekir

@blubberdiblub Şüphelendiğim şey buydu ANCAK projemiz yalnızca python 3.5 virtualenv üzerinde çalışıyor. Kodun bir python 2 projesinden kopyalanmış olması gerektiğini düşünüyorum.
RFV5s

@RFVenter yup, bu başka bir açıklama olabilir. Ve elbette, yalnızca Python 3.x ise, nesne referanslarından kurtulmakta sorun yok.
blubberdiblub

17

Python 3'te üç farklı yolla bir sınıf oluşturabilirsiniz ve dahili olarak hepsi eşittir (örneklere bakın). Bir sınıfı nasıl oluşturduğunuz önemli değil, python 3'teki tüm sınıflar, nesne adı verilen özel sınıftan miras alır . Sınıf nesnesi python'daki temel sınıftır ve çift alt çizgi yöntemleri, tanımlayıcılar, super () yöntemi, özellik () yöntemi vb. Gibi birçok işlevsellik sağlar.

Örnek 1.

class MyClass:
 pass

Örnek 2.

class MyClass():
 pass

Örnek 3.

class MyClass(object):
  pass

1
Bu kesinlikle doğru değil ... stackoverflow.com/questions/1238606/…
Philip Adler

Seni takip ettiğimden emin değilim. Ve evet, alakalı olana kadar muhtemelen çoğu insanla alakalı değil.
Philip Adler

@PhilipAdler Genelde objectyerleşik olana gönderme yaptığı varsayılır object. Herhangi bir CPython'un yerleşik tanımlayıcısının değiştirilebileceğini hesaba katarsak, veri modeli hakkında zar zor iddia edebiliriz. strBir dizgeyi her zaman bir argüman olarak kabul etmediği için ciddi bir şekilde tartışılabilir builtins.str = Nonemi?
Nuno André

Bunun "yaygın olarak varsayıldığına" dair bu iddiayı görüyorum ve her mevcut uygulamanın yaptığı bir varsayım olduğunu kabul ediyorum (bu dilin bir gerekliliği değil), python programcılarının çoğunun benim deneyimim olmadığını tanışmış, bunu varsaymış, bunu biliyor veya hatta düşünmüş. Hangisi olursa olsun, doğru olsa bile yaygın olarak varsayıldığı iddiası, eşdeğerliğin kesinlikle doğru olmadığı yönündeki iddiamı geçersiz kılmaz .
Philip Adler

1

Evet, tüm Python sınıfları nesneyi genişletmelidir (veya daha doğrusu alt sınıf, buradaki Python). Normalde ciddi sorunlar ortaya çıkmazken, bazı durumlarda (çoklu miras ağaçlarında olduğu gibi) bu önemli olacaktır. Bu aynı zamanda Python 3 ile daha iyi uyumluluk sağlar.


1
tam olarak, teknik olarak, eğer almazsanız, klasik bir sınıf elde edersiniz, ancak bunun gerçek bir avantajı yoktur ve yine de python 3 tarafından desteklenmez
max k.

Python3 ile uyumluluğu neden iyileştirdiğini merak ediyorum. Anladığım kadarıyla, python3 onu belirtmeseniz bile nesneyi otomatik olarak genişletecek, değil mi?
Paul Lo

2
@PaulLo Doğru, ancak açıkça nesneden miras alırsanız, hem Python 2 hem de Python 3'te aynı (yeni stil) davranışı elde edeceksiniz. Bu Python 3'ün nasıl çalıştığını değiştirmekle ilgili değil, ileriye doğru kullanmakla ilgili
-Python

Bu öneri pek şık görünmüyor, ancak Python2 ve Python3'e hitap etmeniz durumunda etkili görünüyor. Ama pratikte ne kadar alakalı?
Wolf

@Wolf Ne yaptığınıza bağlı. Karmaşık miras ağaçlarınız varsa, bu oldukça önemlidir. Sınıfınızın tanımlayıcı olmasını istiyorsanız, yeni stil kullanmalısınız. Daha ayrıntılı bilgi istiyorsanız stackoverflow.com/questions/54867/… adresinden bağlantıları takip edebilirsiniz .
pydsigner

1

Diğer yanıtların da kapsadığı gibi, nesneden Python 3 kalıtımı örtüktür. Ancak ne yapmanız gerektiğini ve geleneğin ne olduğunu belirtmiyorlar.

Python 3 dokümantasyon örneklerinin tümü, kural olan aşağıdaki stili kullanır, bu yüzden Python 3'te gelecekteki herhangi bir kod için bunu izlemenizi öneririm.

class Foo:
    pass

Kaynak: https://docs.python.org/3/tutorial/classes.html#class-objects

Örnek alıntı:

Sınıf nesneleri iki tür işlemi destekler: öznitelik referansları ve somutlaştırma.

Öznitelik başvuruları, Python: obj.name'deki tüm öznitelik başvuruları için kullanılan standart sözdizimini kullanır. Geçerli öznitelik adları, sınıf nesnesi oluşturulduğunda sınıfın ad alanında bulunan tüm adlardır. Öyleyse, sınıf tanımı şöyle görünüyorsa:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

Başka bir alıntı:

Genel olarak, örnek değişkenleri her örneğe özgü veriler içindir ve sınıf değişkenleri, sınıfın tüm örnekleri tarafından paylaşılan öznitelikler ve yöntemler içindir:

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):
        self.name = name    # instance variable unique to each instance

0

python3'te bir fark yoktur, ancak python2'de genişletmemek objectsize eski tarz sınıflar verir; eski tarz bir sınıfa göre yeni tarz bir sınıf kullanmak istersiniz.


2
Bu yanıt mantıklıdır, ancak diğer yanıtlayıcılar oraya daha hızlı ve / veya daha ayrıntılı olarak ulaştı; bu cevap, bulunduğu haliyle sayfaya herhangi bir değer katmıyor.
Mark Amery
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.