ข้อความ“ วิธีการสาธารณะน้อยเกินไป” ของไพลินท์หมายความว่าอย่างไร


110

ฉันใช้ไพลินต์กับโค้ดบางโค้ดและได้รับข้อผิดพลาด "มีวิธีการสาธารณะน้อยเกินไป (0/2)" ข้อความนี้หมายความว่าอย่างไร เอกสาร pylintจะไม่เป็นประโยชน์:

ใช้เมื่อชั้นเรียนมีวิธีการสาธารณะน้อยเกินไปดังนั้นอย่าลืมว่ามันคุ้มค่าจริงๆ


1
ชั้นเรียนของคุณมีลักษณะอย่างไร? ชั้นเรียนทำอย่างอื่นนอกเหนือจากการจัดเก็บข้อมูลหรือไม่
Blender

1
ทุกชั้นเรียนคือการจัดเก็บข้อมูล
monsur

2
นั่นคือปัญหาของคุณ ชั้นเรียนไม่ได้มีไว้เพื่อจัดเก็บข้อมูล นั่นคือโครงสร้างข้อมูลเช่นพจนานุกรมและรายการมีไว้สำหรับ
Blender

น่าสนใจขอบคุณ! ข้อความแสดงข้อผิดพลาด pylint อาจมีประโยชน์มากขึ้น อย่างไรก็ตามอย่าลังเลที่จะเปลี่ยนความคิดเห็นของคุณให้เป็นคำตอบและฉันจะอนุมัติ
monsur

6
แต่นิยามของคำว่า "ไม่กี่" อยู่ที่ไหน? ฉันมีวิธีการเดียว นั่นคือเหตุผลที่มีชั้นเรียน ไพลินท์กำหนด "ไม่กี่" ได้อย่างไร? มากกว่า 2? ทำไม?
Zordid

คำตอบ:


124

ข้อผิดพลาดโดยทั่วไปกล่าวว่าคลาสไม่ได้มีไว้เพื่อจัดเก็บข้อมูลเพียงอย่างเดียวเนื่องจากคุณถือว่าชั้นเรียนเป็นพจนานุกรม ชั้นเรียนควรมีวิธีการอย่างน้อยสองสามวิธีในการดำเนินการกับข้อมูลที่พวกเขาเก็บไว้

หากชั้นเรียนของคุณมีลักษณะดังนี้:

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

ลองใช้พจนานุกรมหรือ a namedtupleแทน แม้ว่าชั้นเรียนจะเป็นทางเลือกที่ดีที่สุดให้ใช้ ไพลินท์ไม่เคยรู้ว่าอะไรดีที่สุด

โปรดทราบว่าnamedtupleไม่เปลี่ยนรูปและค่าที่กำหนดในการสร้างอินสแตนซ์ไม่สามารถแก้ไขได้ในภายหลัง


73
+1 สำหรับ "pylint ไม่ทราบว่าสิ่งที่ดีที่สุด" - ใช้วิจารณญาณของตัวเอง แต่เป็นกฎถ้าสิ่งที่คุณต้องการคือ "โครงสร้าง" ใช้หรือdict namedtupleใช้คลาสเมื่อคุณต้องการเพิ่มตรรกะบางอย่างให้กับวัตถุของคุณ (ตัวอย่างเช่นคุณต้องการให้สิ่งต่างๆเกิดขึ้นเมื่อสร้างขึ้นคุณต้องการสิ่งพิเศษบางอย่างที่จะเกิดขึ้นเมื่อมีการเพิ่มคุณต้องการให้ดำเนินการบางอย่างกับมันควบคุมวิธีการ แสดง ฯลฯ )
Burhan Khalid

ขอบคุณสำหรับคำตอบโดยละเอียด! กรณีการใช้งานของฉันคล้ายกับที่ Burhan กล่าวถึงฉันกำลังดำเนินการประมวลผลข้อมูลเมื่อสร้างขึ้น
monsur

6
ข้อผิดพลาดนี้ไม่สมเหตุสมผลหากคุณมี Meta (metaclass) อยู่ในนิยามคลาสของคุณ
alexander_ch

12
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

    ...             

แม้ว่าคุณจะขยายเพียงฟังก์ชันเดียว แต่คุณต้องมีคลาสเพื่อสร้างฟังก์ชันเทคนิคนี้และการขยายนั้นดีกว่าการแฮ็กคลาสของบุคคลที่สามอย่างแน่นอน!


การมี diable นี้การกระทำล่วงหน้าตอนนี้ให้ฉัน: ค่าตัวเลือกที่ไม่ถูกต้อง 'น้อยเกินไป - วิธีสาธารณะ' (ค่าตัวเลือกที่ไม่ดี)
ปรอท

คุณรวม 's' ในวิธีการหรือไม่? ไม่มีข้อความ bad-option-value ของคุณ
sage

4
วิธีที่ดีกว่าในการปิดการใช้งานนี้คือการตั้งค่าmin-public-methods=0ใน[BASIC]ส่วนของไฟล์กำหนดค่า สิ่งนี้ช่วยให้คุณวางไว้ในบรรทัดแยกต่างหากจากทุกdisable=สิ่งของคุณ(ใน[MESSAGE CONTROL]) ซึ่งฉันพบว่าทำให้การเพิ่มความคิดเห็นโดยละเอียดง่ายขึ้นเกี่ยวกับสาเหตุที่คุณเปิดใช้งานและปิดใช้งานสิ่งต่างๆพร้อมกับการเปลี่ยนแปลงการกำหนดค่า
cjs

15

นี่เป็นอีกกรณีหนึ่งของpylintกฎตาบอด

"ชั้นเรียนไม่ได้มีไว้เพื่อจัดเก็บข้อมูล" - นี่เป็นข้อความเท็จ พจนานุกรมไม่ได้ดีสำหรับทุกอย่าง สมาชิกข้อมูลของคลาสเป็นสิ่งที่มีความหมายรายการพจนานุกรมเป็นสิ่งที่ไม่บังคับ หลักฐาน: คุณสามารถdictionary.get('key', DEFAULT_VALUE)ป้องกัน a KeyErrorได้ แต่ไม่มี__getattr__ค่าเริ่มต้นง่ายๆ

แก้ไข - วิธีที่แนะนำสำหรับการใช้โครงสร้าง

ฉันต้องการอัปเดตคำตอบของฉัน ตอนนี้ - หากคุณต้องการstructคุณมีสองตัวเลือกที่ยอดเยี่ยม:

ก) เพียงใช้ 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แม้ใน Python 2) และอื่น ๆ

b) ใช้dataclasses(Py 3.7+)

ตามความคิดเห็นของ hwjp ฉันขอแนะนำdataclasses:

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

เกือบจะดีพอ ๆ กับattrsและเป็นกลไกไลบรารีมาตรฐาน ("รวมแบตเตอรี่") โดยไม่มีการอ้างอิงเพิ่มเติมยกเว้น Python 3.7+

คำตอบก่อนหน้าที่เหลือ

NamedTupleไม่ดี - โดยเฉพาะอย่างยิ่งก่อน python 3 typing.NamedTuple: https://docs.python.org/3/library/typing.html#typing.NamedTuple - คุณควรตรวจสอบNamedTupleรูปแบบ"คลาสที่ได้มาจาก" อย่างแน่นอน Python 2 - namedtuplesสร้างจากคำอธิบายสตริง - น่าเกลียดไม่ดีและ "การเขียนโปรแกรมภายในตัวอักษรสตริง" โง่

ฉันเห็นด้วยกับสองคำตอบในปัจจุบัน ("ลองใช้อย่างอื่น แต่ไพลินท์ไม่ถูกต้องเสมอไป" - คำตอบที่ยอมรับและ "ใช้ไพลินท์ระงับความคิดเห็น") แต่ฉันมีข้อเสนอแนะของตัวเอง

ผมขอชี้นี้ออกมาอีกครั้งหนึ่ง: บางคนเรียนมีความหมายเพียงแค่การเก็บข้อมูล

ตอนนี้ตัวเลือกที่ต้องพิจารณา - ใช้property-ies

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

ด้านบนคุณมีคุณสมบัติแบบอ่านอย่างเดียวซึ่งก็ใช้ได้สำหรับ Value Object (เช่นเช่นเดียวกับที่อยู่ใน Domain Driven Design) แต่คุณยังสามารถจัดหา setters ได้ด้วยวิธีนี้คลาสของคุณจะสามารถรับผิดชอบฟิลด์ที่คุณมีได้เช่น เพื่อทำการตรวจสอบความถูกต้องบางอย่างเป็นต้น (หากคุณมีตัวตั้งค่าคุณสามารถกำหนดโดยใช้สิ่งเหล่านี้ในตัวสร้างได้เช่นself.foo = fooแทนที่จะเป็นโดยตรงself._foo = fooแต่ระวังตัวตั้งค่าอาจถือว่าฟิลด์อื่นได้รับการเตรียมใช้งานแล้วและคุณต้องมีการตรวจสอบความถูกต้องแบบกำหนดเองในตัวสร้าง) .


2
ใน Python 3.7 ขึ้นไป dataclasses เป็นทางออกที่ดีโดยระบุถึงความน่าเกลียดบางอย่างของ namestuples และเหมาะสำหรับ DDD Value Objects
hwjp

ฉันเห็นด้วยและตั้งแต่ปี 2020 เป็นต้นไปเป็นวิธีมาตรฐานที่จะไป หากต้องการมีกลไกช่วงกว้าง (2.7, 3.3+ ถ้าฉันจำได้) คุณสามารถใช้attrsไลบรารีซึ่งเป็นพิมพ์เขียวในการสร้างdataclassesโมดูล
Tomasz Gandor

namedtuplesมีไวยากรณ์แปลก ๆ สำหรับการสืบทอด ... ต้องการให้ทุกชั้นเรียนรู้ว่าเป็นทูเปิลที่มีชื่อและใช้__new__แทน__init__. dataclassesไม่มีข้อ จำกัด นี้
Erik Aronesty

4

เป็นเรื่องยากเมื่อเจ้านายของคุณคาดหวังหลักการความรับผิดชอบเดียว แต่ไพลินท์บอกว่าไม่ ดังนั้นให้เพิ่มวิธีที่สองในชั้นเรียนของคุณเพื่อให้ชั้นเรียนของคุณละเมิดหลักการความรับผิดชอบเดียว คุณตั้งใจที่จะยึดหลักความรับผิดชอบเดียวแค่ไหนอยู่ในสายตาของผู้มอง

การแก้ไขของฉัน

ฉันได้เพิ่มวิธีการพิเศษในชั้นเรียนของฉันดังนั้นตอนนี้จึงมี 2 อย่าง

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

ฉันแค่สงสัยว่าตอนนี้ฉันต้องแบ่งคลาสออกเป็น 2 ไฟล์แยกกันหรือไม่และอาจจะเป็นโมดูลด้วย

ปัญหาได้รับการแก้ไข แต่ไม่ใช่กับเพื่อนร่วมงานของฉันที่ใช้เวลาทั้งวันในการโต้เถียงเรื่องสเป็คแทนที่จะจัดการกับมันเหมือนชีวิตและความตาย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.