Pylint'in "Çok az genel yöntem" mesajı ne anlama geliyor?


110

Pylint'i bazı kodlarda çalıştırıyorum ve "Çok az genel yöntem (0/2)" hatası alıyorum. Bu mesajın anlamı nedir? PyLint dokümanlar yararlı değildir:

Sınıfın çok az genel yöntemi olduğunda kullanılır, bu yüzden gerçekten değdiğinden emin olun.


1
Sınıfınız neye benziyor? Sınıf, verileri depolamaktan başka bir şey yapıyor mu?
Blender

1
Sınıfın tek yaptığı veri depolamaktır.
monsur

2
İşte sorunun var. Sınıflar veri depolamaya yönelik değildir. Sözlükler ve listeler gibi veri yapıları bunun içindir.
Blender

İlginç, teşekkürler! Pilin hata mesajı daha kullanışlı hale getirilebilir. Her neyse, yorumunuzu bir cevaba çevirmekten çekinmeyin, ben de onaylayacağım.
monsur

6
Ama "az" ın tanımı nerede? Tam olarak bir yöntemim var. Sınıfın var olmasının nedeni budur. Pilin "az" ı nasıl tanımlar? 2'den fazla mı? Neden?
Zordid

Yanıtlar:


124

Hata temelde sınıfları anlamına gelmediğini söylüyor sadece temelde bir sözlük olarak sınıf davrandığınız gibi veri depolamak. Sınıflar, tuttukları veriler üzerinde işlem yapmak için en az birkaç yönteme sahip olmalıdır.

Sınıfınız böyle görünüyorsa:

class MyClass(object):
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar

namedtupleBunun yerine bir sözlük veya a kullanmayı düşünün . Bir sınıf en iyi seçenek gibi görünse de, onu kullanın. pylint her zaman neyin en iyi olduğunu bilmez.

Bunun namedtupledeğişmez olduğunu ve somutlaştırmada atanan değerlerin daha sonra değiştirilemeyeceğini unutmayın.


73
"Pilint en iyi olanı bilmiyor" için +1 - kendi kararınızı kullanın, ancak kural olarak, ihtiyacınız olan şey bir "yapı" ise, dictveya kullanın namedtuple. Nesnenize biraz mantık eklemek istediğinizde bir sınıf kullanın (örneğin, bir şeylerin oluşturulduğunda olmasını istiyorsanız, eklendiğinde bazı özel şeylere ihtiyacınız var, üzerinde bazı işlemler gerçekleştirmek, nasıl olduğunu kontrol etmek istiyorsunuz. görüntüleniyor, vb.)
Burhan Khalid

Ayrıntılı yanıtlar için teşekkürler! Benim kullanım durumum Burhan'ın bahsettiğine benzer, veriler oluşturulurken üzerinde bazı işlemler yapıyorum.
monsur

6
Sınıf tanımınızda Meta (metasınıf) varsa bu hata bir anlam ifade etmez.
alexander_ch

12
namedtupleberbat - çirkin sözdizimine sahip olmanın yanı sıra, onu belgeleyemez veya varsayılan değerleri kolayca sağlayamazsınız.
rr-

6
Her kullandığımda namedtuplekarardan pişman oldum. Hem adlandırılmış erişime hem de dizine alınmış erişim özniteliklerine izin vermek tutarsızdır.
teorifice

39

Bir sınıfı genişletiyorsanız, önerim bu uyarıyı sistematik olarak devre dışı bırakmak ve devam etmek, örneğin Kereviz görevleri durumunda:

class MyTask(celery.Task):  # pylint: disable=too-few-public-methods                                                                                   
    """base for My Celery tasks with common behaviors; extends celery.Task

    ...             

Yalnızca tek bir işlevi genişletiyor olsanız bile, bu tekniğin işlevini yerine getirmek için kesinlikle bir sınıfa ihtiyacınız var ve genişletme kesinlikle üçüncü taraf sınıfları hacklemekten daha iyidir!


Bu diable'a sahip olmak, ön taahhüt şimdi bana şunu veriyor: Kötü seçenek değeri 'çok az halka açık yöntem' (kötü seçenek değeri)
Mercury

Yöntemlere 's' harfini eklediniz mi? Kötü seçenek-değer mesajınızda yok.
sage

4
Muhtemelen bu devre dışı bırakmak için daha iyi bir yolu ayarlamaktır min-public-methods=0içinde [BASIC]yapılandırma dosyasının bölümüne. Bu, onu bulduğum tüm disable=öğelerinizden (içinde [MESSAGE CONTROL]) ayrı bir satıra koymanıza izin verir , yapılandırma değişikliği ile birlikte şeyleri neden etkinleştirdiğiniz ve devre dışı bıraktığınız hakkında ayrıntılı yorumlar eklemeyi kolaylaştırır.
cjs

15

Bu, başka bir pylintkör kural durumudur .

"Sınıflar veri depolamaya yönelik değildir" - bu yanlış bir ifadedir. Sözlükler her şey için iyi değildir. Bir sınıfın veri üyesi anlamlı, sözlük öğesi ise isteğe bağlı bir şeydir. Kanıt: a'yı dictionary.get('key', DEFAULT_VALUE)önlemek için yapabilirsiniz KeyError, ancak __getattr__varsayılan ile basit bir şey yoktur .

EDIT - yapıları kullanmak için önerilen yollar

Cevabımı güncellemem gerekiyor. Şu anda - a'ya ihtiyacınız structvarsa, iki harika seçeneğiniz var:

a) Sadece kullan attrs

Bunlar bunun için bir kitaplık:

https://www.attrs.org/en/stable/

import attr

@attr.s
class MyClass(object):  # or just MyClass: for Python 3
    foo = attr.ib()
    bar = attr.ib()

Fazladan ne elde edersiniz: kurucular, varsayılan değerler, doğrulama __repr__, salt okunur nesneler ( namedtuplesPython 2'de bile değiştirmek için ) ve daha fazlasını yazmamak.

b) Kullan dataclasses(Py 3.7+)

Hwjp'nin yorumundan sonra şunu da tavsiye ederim dataclasses:

https://docs.python.org/3/library/dataclasses.html

Bu neredeyse en az onun kadar iyidir attrsve Python 3.7+ dışında ekstra bağımlılık içermeyen standart bir kitaplık mekanizmasıdır ("piller dahil").

Önceki yanıtın geri kalanı

NamedTupleharika değil - özellikle python 3'lerden önce typing.NamedTuple: https://docs.python.org/3/library/typing.html#typing.NamedTuple - "türetilmiş sınıf NamedTuple" kalıbına kesinlikle göz atmalısınız . Python 2 - namedtuplesdize açıklamalarından oluşturulmuş - çirkin, kötü ve "dizge değişmezleri içinde programlama" aptalca.

Şu anki iki yanıta katılıyorum ("başka bir şey kullanmayı düşünün, ancak pylint her zaman doğru değildir" - kabul edilen yanıt ve "pylint bastırıcı yorum kullan"), ancak kendi önerim var.

Bunu bir kez daha belirtmeme izin verin: Bazı sınıflar sadece verileri depolamaya yöneliktir .

Şimdi de dikkate alma seçeneği - property-ies kullanın .

class MyClass(object):
    def __init__(self, foo, bar):
        self._foo = foo
        self._bar = bar

    @property
    def foo(self):
        return self._foo

    @property
    def bar(self):
        return self._bar

Yukarıda, Değer Nesnesi için uygun olan salt okunur özelliklere sahipsiniz (örneğin, Etki Alanına Dayalı Tasarımdakiler gibi), ancak ayarlayıcılar da sağlayabilirsiniz - bu şekilde sınıfınız sahip olduğunuz alanların sorumluluğunu üstlenebilir - örneğin bazı doğrulama yapmak vb. için (ayarlayıcılarınız varsa, bunları kurucuda kullanarak atayabilirsiniz, yani self.foo = foodoğrudan self._foo = foo, ancak dikkatli olmak yerine , ayarlayıcılar diğer alanların zaten başlatılmış olduğunu varsayabilir ve sonra yapıcıda özel doğrulamaya ihtiyacınız vardır) .


2
Python 3.7 ve üzeri sürümlerde, veri sınıfları adlandırılmış çiftlerin bazı çirkinliklerini ele alan iyi bir çözüm sunar ve DDD Değer Nesneleri için mükemmeldir .
hwjp

Katılıyorum ve 2020'den itibaren standart yol bu. Geniş sürüm aralıklı bir mekanizmaya sahip olmak için (hatırlıyorsam 2.7, 3.3+) attrs, aslında dataclassesmodül oluşturmanın planı olan kitaplığı kullanabilirsiniz .
Tomasz Gandor

namedtupleskalıtım için garip bir sözdizimi var ... birini kullanan her sınıfın bunun adlandırılmış bir demet olduğunu bilmesini ve __new__bunun yerine kullanmasını gerektirir __init__. dataclassesbu sınırlamaya sahip değilsiniz
Erik Aronesty

4

Patronunuzun tek sorumluluk ilkesini beklemesi zordur, ancak pylint hayır diyor. Bu yüzden sınıfınıza ikinci bir yöntem ekleyin, böylece sınıfınız tek sorumluluk ilkesini ihlal eder. Tek sorumluluğu ne kadar ileri götürmeniz gerektiği ilkesi, bakanın gözündedir.

Düzeltmem

Sınıfıma fazladan bir yöntem ekledim, bu yüzden şimdi 2 şey yapıyor.

def __str__(self):
    return self.__class__.__name__

Şimdi sınıfımı 2 ayrı dosyaya bölmem gerekip gerekmediğini merak ediyorum ve belki modüller de olabilir.

sorun çözüldü, ancak bütün gününü yaşam ve ölüm gibi onunla uğraşmak yerine şartnameyi tartışarak geçiren meslektaşlarımla değil.

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.