Python'da "Özel" (uygulama) sınıfı


107

İki bölümden oluşan küçük bir Python modülü kodluyorum:

  • bir ortak arayüzü tanımlayan bazı fonksiyonlar,
  • Yukarıdaki işlevler tarafından kullanılan, ancak modül dışında anlamlı olmayan bir uygulama sınıfı.

İlk başta, bu gerçekleme sınıfını, onu kullanarak onu kullanarak işlevin içinde tanımlayarak "gizlemeye" karar verdim, ancak bu okunabilirliği engelliyor ve birden çok işlev aynı sınıfı yeniden kullanıyorsa kullanılamaz.

Öyleyse, yorumlara ve belgelere ek olarak, bir sınıfı "özel" veya "dahili" olarak işaretlemek için bir mekanizma var mı? Alt çizgi mekanizmasının farkındayım, ancak anladığım kadarıyla yalnızca değişkenler, işlev ve yöntem adları için geçerli.

Yanıtlar:


175

Tek bir alt çizgi öneki kullanın:

class _Internal:
    ...

Bu, 'dahili' semboller için resmi Python sözleşmesidir; "modül içe aktarımından *" alt çizgi önekli nesneleri içe aktarmaz.

Düzenleme: Tek alt çizgi kuralına referans


3
Alt çizgi kuralının sınıfları da kapsadığını bilmiyordum. İçe aktarırken ad alanımı karıştırmak istemiyorum, bu nedenle aradığım davranış bu. Teşekkürler!
oparisy

1
Bunun "resmi" python kuralı olduğunu belirttiğinize göre, bir bağlantıyla güzel olur. Buradaki başka bir gönderi, her şeyin resmi yol olduğunu ve belgelere bağlantı verdiğini söylüyor .
flodin

11
python.org/dev/peps/pep-0008 - _single_leading_underscore: zayıf "dahili kullanım" göstergesi. Örneğin, "M'den içe aktarım *", adı bir alt çizgiyle başlayan nesneleri içe aktarmaz. - Dahili kullanım için sınıfların önde gelen bir alt çizgisi vardır
Miles

2
Önde gelen bir alt çizgi, şeyleri dahili olarak işaretleme konvansiyonudur, "bununla uğraşmayın", oysa her şey daha çok "M'den içe aktarım *" ile kullanılmak üzere tasarlanmış modüller için, modül kullanıcılarının dokunmaması gerektiğini ima etmeden o sınıf.
Miles

65

Kısacası:

  1. Gizliliği uygulayamazsınız . Python'da özel sınıflar / yöntemler / işlevler yoktur. En azından, Java gibi diğer dillerdeki gibi katı gizlilik değil.

  2. Yalnızca gizlilik belirtebilir / önerebilirsiniz . Bu bir kongre izler. Bir sınıfı / işlevi / yöntemi özel olarak işaretlemek için kullanılan python kuralı, ona bir _ (alt çizgi) ile başlamaktır. Örneğin, def _myfunc()veya class _MyClass:. Yöntemin önüne iki alt çizgi ekleyerek de sözde gizlilik oluşturabilirsiniz (örneğin:) __foo. Yönteme doğrudan erişemezsiniz, ancak yine de sınıf adını kullanarak özel bir önek aracılığıyla çağırabilirsiniz (örneğin:) _classname__foo. Bu yüzden yapabileceğiniz en iyi şey, gizliliği uygulamak değil, gizliliği belirtmek / önermektir.

Python bu bakımdan perl gibidir. Perl kitabındaki mahremiyetle ilgili meşhur bir cümleyi yorumlayacak olursak, felsefe, oturma odasından uzak durmanız gerektiğidir, çünkü bir av tüfeğiyle savunulduğu için değil, davet edilmediniz.

Daha fazla bilgi için:


1 numaraya yanıt olarak, yöntemlerin gizliliğini uygulayabilirsiniz. __Method (self) gibi bir çift alt çizgi kullanmak, onu sınıfın dışında erişilemez hale getirir. Ancak Foo () ._ Foo__method () diye adlandırmanın bir yolu var. Sanırım onu ​​daha ezoterik bir şeye yeniden adlandırıyor.
Evan Fosmark

1
Bu alıntı doğrudur.
Paul Draper

37

__all__Dışa aktarılmasını istediğiniz adların bir listesini tanımlayın ( belgelere bakın ).

__all__ = ['public_class'] # don't add here the 'implementation_class'

10

Bazen kullandığım bir kalıp şudur:

Bir sınıf tanımlayın:

class x(object):
    def doThis(self):
        ...
    def doThat(self):
        ...

Sınıf adının üzerine yazarak sınıfın bir örneğini oluşturun:

x = x()

İşlevselliği ortaya çıkaran sembolleri tanımlayın:

doThis = x.doThis
doThat = x.doThat

Örneğin kendisini silin:

del x

Artık yalnızca genel işlevlerinizi ortaya çıkaran bir modülünüz var.


2
"Sınıf adının üzerine yazmanın" amacını / işlevini anlamak bir dakika sürdü, ama yaptığımda büyük bir gülümsemeyle karşılaştım. Ne zaman kullanacağımdan emin değilim. :)
Zach Young

Bu tekniğin bir adı var mı?
Bishwas Mishra


4

Tasarım gelenekleri konusuna değinmek için ve Christopher'ın dediği gibi, Python'da gerçekten "özel" diye bir şey yoktur. Bu, C / C ++ arka planından gelen biri için çarpık görünebilir (bir süre önce benim gibi), ancak sonunda, muhtemelen aşağıdaki kuralların yeterince olduğunu anlayacaksınız.

Önünde alt çizgi olan bir şeyi görmek, onu doğrudan kullanmamak için yeterince iyi bir ipucu olmalıdır. help(MyClass)Çıktı dağınıklığı ile ilgileniyorsanız (bir sınıfı nasıl kullanacağınıza dair arama yaparken herkesin baktığı şey budur), altı çizili öznitelikler / sınıflar oraya dahil edilmemiştir, bu nedenle sadece "genel" arayüzünüzün tanımlanmasıyla sonuçlanırsınız.

Ayrıca, herkese açık olan her şeye sahip olmanın kendi harika avantajları vardır, örneğin, dışarıdan hemen hemen her şeyi birim test edebilirsiniz (ki bunu C / C ++ özel yapılarla gerçekten yapamazsınız).


4

"Özel" tanımlayıcıların önek adları için iki alt çizgi kullanın. Bir modüldeki sınıflar için tek bir alt çizgi kullanın ve bunlar "modül içe aktarımından *" kullanılarak içe aktarılmayacaktır.

class _MyInternalClass:
    def __my_private_method:
        pass

(Python'da gerçek "özel" diye bir şey yoktur. Örneğin, Python, sınıf üyelerinin adlarını çift alt çizgi ile otomatik olarak __clssname_mymemberkarıştırır. Yani gerçekten, eğer karıştırılmış adı biliyorsanız, yine de "özel" varlığı kullanabilirsiniz. . buraya bakın. ) Ve eğer istedim tabii el ithal "iç" sınıfları tercih edebilirsiniz.


Neden iki _? Bir yeterlidir.
S.Lott

"İçe aktarmanın" sınıfları ve işlevleri içe aktarmasını önlemek için tek bir alt çizgi yeterlidir. Python'un isim değiştirme özelliğini teşvik etmek için iki alt çizgiye ihtiyacınız var. Daha net olmalıydı; Ben düzenledim.
chroder

Şimdi, takip. Neden isim bozmak? Bunun olası faydası nedir?
S.Lott

5
Olası fayda, bu değişkenlere erişmesi gereken diğer geliştiricileri can sıkıcıdır :)
Richard Levasseur
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.