पाइलिंट के "बहुत कम सार्वजनिक तरीकों" संदेश का क्या मतलब है


110

मैं कुछ कोड पर पाइलिंट चला रहा हूं, और "बहुत कम सार्वजनिक तरीके (0/2)" त्रुटि प्राप्त कर रहा हूं। इस संदेश का क्या अर्थ है? Pylint डॉक्स उपयोगी नहीं हैं:

जब क्लास में बहुत कम सार्वजनिक विधियां होती हैं, तो सुनिश्चित करें कि यह वास्तव में इसके लायक है।


1
आपकी कक्षा कैसी दिखती है? क्या क्लास डेटा स्टोर करने के अलावा कुछ नहीं करता है?
ब्लेंडर

1
सभी वर्ग डेटा संग्रहीत करता है।
महाशय

2
खैर, आपकी समस्या है। कक्षाएं डेटा संग्रहीत करने के लिए नहीं हैं। यही कारण है कि शब्दकोशों और सूचियों जैसी डेटा संरचनाएं हैं।
ब्लेंडर

दिलचस्प है, धन्यवाद! पाइलिंट त्रुटि संदेश को अधिक उपयोगी बनाया जा सकता है। वैसे भी, अपनी टिप्पणी को एक उत्तर में बदलने के लिए स्वतंत्र महसूस करें और मैं इसे स्वीकार करूंगा।
महाशय

6
लेकिन "कुछ" की परिभाषा कहाँ है? मुझे बिल्कुल एक तरीका मिला। यही कारण है कि वर्ग मौजूद है। पाइलिंट "कुछ" को कैसे परिभाषित करता है? 2 से अधिक? क्यों?
जोर्डिड

जवाबों:


124

मूल रूप से त्रुटि यह कहती है कि कक्षाएं केवल डेटा स्टोर करने के लिए नहीं हैं , क्योंकि आप मूल रूप से कक्षा को शब्दकोश के रूप में मान रहे हैं। डेटा रखने के लिए कक्षाओं में कम से कम कुछ विधियाँ होनी चाहिए।

यदि आपकी कक्षा इस तरह दिखती है:

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

एक शब्दकोश या namedtupleइसके बजाय का उपयोग करने पर विचार करें । यद्यपि यदि कोई वर्ग सबसे अच्छा विकल्प लगता है, तो इसका उपयोग करें। pylint हमेशा नहीं जानता कि सबसे अच्छा क्या है।

ध्यान दें कि namedtupleअपरिवर्तनीय है और तात्कालिकता पर निर्दिष्ट मूल्यों को बाद में संशोधित नहीं किया जा सकता है।


72
+1 के लिए "पाइलिंट को पता नहीं है कि क्या सबसे अच्छा है" - अपने स्वयं के निर्णय का उपयोग करें लेकिन एक नियम के रूप में, अगर आपको जिस चीज की आवश्यकता है वह "संरचना" है, तो dictया का उपयोग करें namedtuple। जब आप अपने ऑब्जेक्ट में कुछ लॉजिक जोड़ना चाहते हैं तो एक क्लास का उपयोग करें (उदाहरण के लिए, आप चाहते हैं कि सामान तब बने जब वह बन जाए, आपको कुछ विशेष चीजों की आवश्यकता होती है जब इसे जोड़ा जाता है, तो आप चाहते हैं कि ओ इस पर कुछ ऑपरेशन करें, इसे कैसे नियंत्रित करें प्रदर्शित, आदि)
बुरहान खालिद

विस्तृत प्रतिक्रियाओं के लिए धन्यवाद! मेरा उपयोग मामला बुरहान के उल्लेख के समान है, मैं इसके निर्माण पर डेटा पर कुछ प्रसंस्करण कर रहा हूं।
महाशय

6
यह त्रुटि समझ में नहीं आती है यदि आपके पास वर्ग परिभाषा के अंदर मेटा (मेटाक्लास) है।
अलेक्जेंडर_च

11
namedtupleबेकार है - बदसूरत सिंटैक्स होने के कारण, आप इसे दस्तावेज़ नहीं कर सकते या आसानी से डिफ़ॉल्ट मान प्रदान नहीं कर सकते।
rr-

6
हर बार जब मैंने प्रयोग किया है तो namedtupleमुझे निर्णय पर पछतावा है। यह नामांकित अभिगम और अनुक्रमित पहुंच विशेषताओं दोनों की अनुमति देने के लिए असंगत है।
सिद्धांत १५'१६ को

39

यदि आप एक वर्ग का विस्तार कर रहे हैं, तो मेरा सुझाव इस चेतावनी को व्यवस्थित रूप से अक्षम करना और आगे बढ़ना है, जैसे, अजवाइन कार्यों के मामले में:

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

    ...             

यहां तक ​​कि अगर आप केवल एक फ़ंक्शन का विस्तार कर रहे हैं, तो आपको निश्चित रूप से इस तकनीक को कार्य करने के लिए एक वर्ग की आवश्यकता है, और तीसरे पक्ष की कक्षाओं पर हैकिंग की तुलना में विस्तार करना निश्चित रूप से बेहतर है!


इस व्यवहार्य होने के बाद, पूर्व-वचन अब मुझे देता है: खराब विकल्प मूल्य 'बहुत-कुछ-सार्वजनिक-विधि' (बुरा-विकल्प-मूल्य)
बुध

क्या आपने विधियों में 's' को शामिल किया है? आपके खराब-विकल्प-मूल्य संदेश में यह नहीं है।
ऋषि

4
संभवतः इसे अक्षम करने का एक बेहतर तरीका कॉन्फ़िगरेशन फ़ाइल min-public-methods=0के [BASIC]अनुभाग में सेट करना है । इससे आप इसे अपने सभी disable=सामानों (इन [MESSAGE CONTROL]) से एक अलग लाइन पर रख सकते हैं, जो मुझे लगता है कि कॉन्फ़िगर परिवर्तन के साथ-साथ आपने सक्षम और अक्षम चीजों के बारे में विस्तृत टिप्पणियां जोड़ना आसान बना दिया है।
css

15

यह pylintअंधे नियमों का एक और मामला है।

"कक्षाएं डेटा संग्रहीत करने के लिए नहीं हैं" - यह एक गलत कथन है। शब्दकोश सब कुछ के लिए अच्छा नहीं हैं। एक कक्षा का एक डेटा सदस्य कुछ सार्थक है, एक शब्दकोष कुछ वैकल्पिक है। प्रमाण: आप इसे dictionary.get('key', DEFAULT_VALUE)रोकने के लिए कर सकते हैं KeyError, लेकिन __getattr__डिफ़ॉल्ट के साथ कोई सरल नहीं है ।

EDIT - संरचना का उपयोग करने के लिए अनुशंसित तरीके

मुझे अपना उत्तर अपडेट करने की आवश्यकता है। अभी - अगर आपको जरूरत है struct, तो आपके पास दो बेहतरीन विकल्प हैं:

a) बस उपयोग करें attrs

ये उसके लिए एक पुस्तकालय है:

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()

आपको क्या अतिरिक्त मिलेगा: कंस्ट्रक्टर, डिफॉल्ट वैल्यू, वेलिडेशन __repr__, रीड-ओनली ऑब्जेक्ट्स (रिप्लेस करने के लिए namedtuples, यहां तक ​​कि पायथन 2 में भी) नहीं लिखना ।

b) उपयोग dataclasses(Py 3.7+)

Hwjp की टिप्पणी के बाद, मैं भी सिफारिश करता हूं dataclasses:

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

यह लगभग उतना ही अच्छा है attrs, और एक मानक पुस्तकालय तंत्र ("बैटरी शामिल है") है, जिसमें कोई अतिरिक्त निर्भरता नहीं है, सिवाय पायथन 3.7+ के।

शेष पिछला उत्तर

NamedTupleमहान नहीं है - विशेष रूप से अजगर 3 से पहले typing.NamedTuple: https://docs.python.org/3/library/typing.html#typing.NamedTuple - आपको निश्चित रूप से "वर्ग NamedTuple" पैटर्न से प्राप्त होना चाहिए । पायथन 2 - namedtuplesस्ट्रिंग विवरण से निर्मित - बदसूरत, खराब और "स्ट्रिंग लिटरल्स के अंदर प्रोग्रामिंग" बेवकूफ है।

मैं दो वर्तमान उत्तरों से सहमत हूं ("कुछ और का उपयोग करने पर विचार करें, लेकिन पाइलिंट हमेशा सही नहीं होता है" - स्वीकृत एक, और "पाइलिंट दबाने वाली टिप्पणी का उपयोग करें"), लेकिन मेरा अपना सुझाव है।

मुझे इसे एक बार और इंगित करने दें: कुछ कक्षाएं केवल डेटा स्टोर करने के लिए होती हैं।

अब विकल्प पर भी विचार करें - उपयोग property-ज।

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

ऊपर आपके पास केवल-पढ़ने के लिए गुण हैं, जो मान ऑब्जेक्ट के लिए ठीक है (जैसे कि डोमेन ड्रिवेन डिज़ाइन में), लेकिन आप सेटर भी प्रदान कर सकते हैं - इस तरह आपकी कक्षा उन क्षेत्रों की ज़िम्मेदारी ले सकेगी जो आपके पास हैं - उदाहरण के लिए कुछ सत्यापन करने के लिए आदि (यदि आपके पास बसने वाले हैं, तो आप उन्हें कंस्ट्रक्टर में उपयोग कर सकते हैं, अर्थात self.foo = fooप्रत्यक्ष के बजाय self._foo = foo, लेकिन सावधानी से, बसने वाले अन्य क्षेत्रों को पहले से ही आरंभिक मान सकते हैं, और फिर आपको निर्माणकर्ता में कस्टम सत्यापन की आवश्यकता होगी) ।


2
Python 3.7 और इसके बाद के संस्करण में, dataclasses कुछ अच्छे समाधान प्रदान करते हैं, कुछ नामांकितों की बदसूरती को संबोधित करते हैं, और वे DDD मान ऑब्जेक्ट के लिए एकदम सही हैं ।
hwjp

मैं सहमत हूं, और 2020 से यह जाने का मानक तरीका है। एक विस्तृत-संस्करण-श्रेणी तंत्र (2.7, 3.3+ अगर मुझे याद है) के लिए आप attrsपुस्तकालय का उपयोग कर सकते हैं , जो वास्तव में dataclassesमॉड्यूल बनाने का खाका था ।
टॉमस गैंडर

namedtuplesवंशानुक्रम के लिए अजीब वाक्यविन्यास है ... प्रत्येक वर्ग को यह जानने के लिए एक का उपयोग करने की आवश्यकता है कि यह एक नामित टपल है और __new__इसके बजाय उपयोग करें __init__dataclassesयह सीमा नहीं है
एरिक एरोनिटी

4

यह कठिन है जब आपका बॉस एकल जिम्मेदारी सिद्धांत की उम्मीद करता है, लेकिन पाइलिंट कहता है कि नहीं। इसलिए अपनी कक्षा में दूसरी विधि जोड़ें ताकि आपका वर्ग एकल जिम्मेदारी सिद्धांत का उल्लंघन करे। जहां तक ​​आप एकल जिम्मेदारी सिद्धांत लेने के लिए हैं, वह देखने वाले की नजर में है।

मेरा फिक्स,

मैंने अपनी कक्षा में एक अतिरिक्त विधि जोड़ी है, इसलिए अब यह 2 चीजें करता है।

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

मैं अभी सोच रहा हूँ कि क्या मुझे अपनी कक्षा को 2 अलग-अलग फ़ाइलों में विभाजित करने की आवश्यकता है, और शायद मॉड्यूल भी।

समस्या हल हो गई, लेकिन मेरे उन सहयोगियों के साथ नहीं, जो सारा दिन कल्पना और बहस करने में बिताते हैं, बजाय इसके कि जीवन और मृत्यु जैसा हो।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.