Python'da sınıf nitelikleri nasıl belgelenir? [kapalı]


115

Öznitelikleri herkesin erişimine açık olan ve yalnızca bazen belirli örneklerde geçersiz kılınan hafif bir sınıf yazıyorum. Python dilinde, sınıf öznitelikleri veya bu konuda herhangi bir öznitelik için belge dizileri oluşturmak için herhangi bir hüküm yoktur. Bu nitelikleri belgelemek için beklenen ve desteklenen yol nedir, bir tane olmalı mı? Şu anda şu tür şeyler yapıyorum:

class Albatross(object):
    """A bird with a flight speed exceeding that of an unladen swallow.

    Attributes:
    """

    flight_speed = 691
    __doc__ += """
        flight_speed (691)
          The maximum speed that such a bird can attain.
    """

    nesting_grounds = "Raymond Luxury-Yacht"
    __doc__ += """
        nesting_grounds ("Raymond Luxury-Yacht")
          The locale where these birds congregate to reproduce.
    """

    def __init__(self, **keyargs):
        """Initialize the Albatross from the keyword arguments."""
        self.__dict__.update(keyargs)

Bu, sınıfın ilk standart docstring bölümünü içeren docstring'in yanı sıra, her öznitelik için artırılmış atama yoluyla eklenen satırlarla sonuçlanacaktır __doc__.

Bu tarz, ülkede açıkça yasak görünmese de docstring stil yönergelerinde de, bir seçenek olarak da belirtilmemiştir. Buradaki avantaj, tanımlarının yanında öznitelikleri belgelemek için bir yol sağlarken, yine de prezentabl bir sınıf dokümanı oluşturması ve docstring'deki bilgileri tekrarlayan yorumlar yazmak zorunda kalmamasıdır. Nitelikleri aslında iki kez yazmak zorunda olduğum için hâlâ biraz kızgınım; En azından varsayılan değerlerin tekrarlanmasını önlemek için docstring'deki değerlerin dize temsillerini kullanmayı düşünüyorum.

Bu, geçici topluluk sözleşmelerinin iğrenç bir ihlali mi? Tamam mı? Daha iyi bir yol var mı? Örneğin, öznitelikler için değerler ve belge dizgileri içeren bir sözlük oluşturmak ve ardından içeriği __dict__sınıf bildiriminin sonuna doğru sınıfa ve docstring'e eklemek mümkündür ; bu, öznitelik adlarını ve değerlerini iki kez yazma ihtiyacını azaltacaktır. Düzenle : bu son fikir, bence, aslında mümkün değil, en azından tüm sınıfı verilerden dinamik olarak inşa etmeden mümkün değil, ki bunu yapmak için başka bir neden yoksa gerçekten kötü bir fikir gibi görünüyor.

Python'da oldukça yeniyim ve hala kodlama stilinin ayrıntıları üzerinde çalışıyorum, bu nedenle ilgisiz eleştiriler de kabul edilir.


Django model niteliklerini belgelemenin bir yolunu arıyorsanız, bu yardımcı olabilir: djangosnippets.org/snippets/2533
Michael Scheper

3
Kopyası Python belge alanları ve özellikleri How? farklı bir çözümü olan.
bufh

1
Bunun neden fikir temelli olduğunu anlamıyorum. Python, özellikle PEP'lerde kabul edilebilir kurallarını belgeler. Uygun şekilde biçimlendirilmiş belgeleri çıkaran farklı Python kaynak araçları vardır. Aslında Python attribute doc string, PEP 257'de iyi bilinmeyen ve OPs sorusuna cevap verebilecek bulması zor görünen ve bazı kaynak araçları tarafından desteklenen bir sözü vardır . Bu bir fikir değil. Bu gerçektir ve dilin bir parçasıdır ve hemen hemen OP'nin istediği şeydir.
NeilG

Yanıtlar:


83

Karışıklığı önlemek için: süreli mülkiyet bir sahiptir anlamı spesifik python. Bahsettiğiniz şey bizim sınıf nitelikleri dediğimiz şeydir . Her zaman kendi sınıfları aracılığıyla harekete geçirildikleri için, onları sınıfın doc dizgisi içinde belgelemenin mantıklı olduğunu görüyorum. Bunun gibi bir şey:

class Albatross(object):
    """A bird with a flight speed exceeding that of an unladen swallow.

    Attributes:
        flight_speed     The maximum speed that such a bird can attain.
        nesting_grounds  The locale where these birds congregate to reproduce.
    """
    flight_speed = 691
    nesting_grounds = "Throatwarbler Man Grove"

Bence bu gözler için, örneğinizdeki yaklaşımdan çok daha kolay. Öznitelik değerlerinin bir kopyasının doc dizesinde görünmesini gerçekten isteseydim, bunları her özniteliğin açıklamasının yanına veya altına koyardım.

Python'da, doc dizelerinin yalnızca kaynak kodu ek açıklamaları değil, belgeledikleri nesnelerin gerçek üyeleri olduğunu unutmayın. Sınıf özniteliği değişkenleri nesnelerin kendileri olmayıp nesnelere referans olduklarından, kendilerine ait doc dizelerini tutmanın bir yolu yoktur. Sanırım referanslardaki belge dizeleri için bir durum oluşturabilirsin, belki de "gerçekte burada olan" yerine "buraya ne gitmeli" ni açıklayabilirsin, ama bunu içeren sınıf doc dizgisinde bunu yapmayı yeterince kolay buluyorum.


Sanırım çoğu durumda bu sorun değil, çünkü nitelikler - terminoloji düzeltmesi için teşekkürler - kısa ve öz bir şekilde, sınıf bildiriminin başlangıcında ileri geri hareket etmeyi pratik olmayıp {ikisini de oku belgeler ve varsayılan değer} veya {belgelerin her iki örneğini ve / veya varsayılan değeri güncelleyin}.
intuited

1
Ayrıca benim örneğimin, özniteliklerin belgelerinin sınıfın docstring'inde görünmesine neden olacağını unutmayın. Aslında dokümantasyonu özniteliklerin kendilerinin dokümantasyonuna koymayı tercih ederim, ancak bu çoğu yerleşik tür için çalışmaz.
intuited

Evet, ilk fikrim sadece örneğin ilan etmekti flight_speed = 691; flight_speed.__doc__ = "blah blah". Sanırım düzenlemenizde bahsettiğiniz şey bu . Ne yazık ki, bu yerleşik türlerin (çoğu?) Somutlaştırılması için işe yaramaz ( intbu örnekte olduğu gibi). Kullanıcı tanımlı türlerin örnekleri için çalışır. =========== Aslında sınıf / modül özellikleri için dokümanlar eklemeyi öneren bir PEP (üzgünüm, sayıyı unutun) vardı, ancak bunu netleştirmenin bir yolunu bulamadıkları için reddedildi Doküman dizgelerinin önceki veya sonraki öznitelikler için olup olmadığı.
intuited

2
Peki ya bunlar örnek niteliklerse? Hala sınıf belgesinde belge mi yoksa ne?
n611x007

1
@intuited Bu PEP miydi? legacy.python.org/dev/peps/pep-0224
taz

30

PEP257: Docstring Conventions'a atıfta bulunuyorsunuz, docstring nedir bölümünde şu ifade edilmektedir:

Python kodunun başka bir yerinde meydana gelen dizgi değişmezleri de belge görevi görebilir. Python bayt kodu derleyicisi tarafından tanınmazlar ve çalışma zamanı nesne öznitelikleri olarak erişilemezler (yani __doc__'a atanmazlar), ancak iki tür ekstra belge dizgisi yazılım araçları tarafından çıkarılabilir:

Bir modülün, sınıfın veya __init__ yönteminin en üst düzeyindeki basit bir atamadan hemen sonra oluşan dize değişmez değerlerine "öznitelik dokümanları" adı verilir.

Ve bu, PEP 258: Nitelik belgelerinde daha ayrıntılı olarak açıklanmıştır. Yukarıda açıklandığı gibi ʇsәɹoɈ. bir öznitelik __doc__ 'a sahip olabilecek bir nesne değildir, bu nedenle içinde help()veya pydoc'ta görünmezler . Bu dokümanlar yalnızca oluşturulan dokümantasyon için kullanılabilir.

Bunlar birlikte Sfenks kullanılan yönerge autoattribute

Sphinx, bir ödevden önceki bir satırda yorumları veya otomatik belgelenecek tanımdan sonraki bir ödev veya bir dokümantasyonun ardından özel bir yorum kullanabilir.


1
jedi-vim eklentisi öznitelik belgelerini de tanır.
Long Vu

1
Bunun ne zaman tanıtıldığını bilmiyorum, ancak Sphinx 1.2.2 oluşturulan dokümantasyonda nitelik dokümanları içeriyor gibi görünüyor.
jochen

1
Teşekkür ederim @jochen, cevabımı güncelliyorum.
marcz

3
Lütfen PEP 258'in reddedildiğini unutmayın. Ret bildirimi şunu belirtir: "Bu, artık bağımsız olan belgeler için ilginç bir tasarım belgesi görevi görebilirken, artık standart kitaplığa eklenmesi planlanmamaktadır."
Michał Łazowik

13

Bu nedenle mülkleri kötüye kullanabilirsiniz. Özellikler bir alıcı, bir ayarlayıcı, bir silici ve bir doküman dizesi içerir . Safça, bu çok ayrıntılı olur:

class C:
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """Docstring goes here."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

O zaman Cx'e ait bir docstring'e sahip olacaksınız:

In [24]: print(C.x.__doc__)
Docstring goes here.

Bunu birçok öznitelik için yapmak zahmetlidir, ancak bir yardımcı işlev myprop düşünebilirsiniz:

def myprop(x, doc):
    def getx(self):
        return getattr(self, '_' + x)

    def setx(self, val):
        setattr(self, '_' + x, val)

    def delx(self):
        delattr(self, '_' + x)

    return property(getx, setx, delx, doc)

class C:
    a = myprop("a", "Hi, I'm A!")
    b = myprop("b", "Hi, I'm B!")

In [44]: c = C()

In [46]: c.b = 42

In [47]: c.b
Out[47]: 42

In [49]: print(C.b.__doc__)
Hi, I'm B!

Ardından, etkileşimli Pythons'ı aradığınızda help:

Help on class C in module __main__:

class C
 |  Data descriptors defined here:
 |  
 |  a
 |      Hi, I'm A!
 |  
 |  b
 |      Hi, I'm B!

ki bence hemen hemen peşinde olduğun şey olmalı.

Düzenleme : Şimdi anlıyorum ki, belki de ilk argümanı geçmek mypropzorunda kalmamalıyız, çünkü iç ismin önemi yok. Sonraki aramalar bir mypropşekilde birbirleriyle iletişim kurabilirse, otomatik olarak uzun ve olası olmayan bir dahili öznitelik adına karar verebilir. Eminim bunu uygulamanın yolları vardır, ancak buna değip değmediklerinden emin değilim.

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.