ฉันใช้ไพลินต์กับโค้ดบางโค้ดและได้รับข้อผิดพลาด "มีวิธีการสาธารณะน้อยเกินไป (0/2)" ข้อความนี้หมายความว่าอย่างไร เอกสาร pylintจะไม่เป็นประโยชน์:
ใช้เมื่อชั้นเรียนมีวิธีการสาธารณะน้อยเกินไปดังนั้นอย่าลืมว่ามันคุ้มค่าจริงๆ
ฉันใช้ไพลินต์กับโค้ดบางโค้ดและได้รับข้อผิดพลาด "มีวิธีการสาธารณะน้อยเกินไป (0/2)" ข้อความนี้หมายความว่าอย่างไร เอกสาร pylintจะไม่เป็นประโยชน์:
ใช้เมื่อชั้นเรียนมีวิธีการสาธารณะน้อยเกินไปดังนั้นอย่าลืมว่ามันคุ้มค่าจริงๆ
คำตอบ:
ข้อผิดพลาดโดยทั่วไปกล่าวว่าคลาสไม่ได้มีไว้เพื่อจัดเก็บข้อมูลเพียงอย่างเดียวเนื่องจากคุณถือว่าชั้นเรียนเป็นพจนานุกรม ชั้นเรียนควรมีวิธีการอย่างน้อยสองสามวิธีในการดำเนินการกับข้อมูลที่พวกเขาเก็บไว้
หากชั้นเรียนของคุณมีลักษณะดังนี้:
class MyClass(object):
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
ลองใช้พจนานุกรมหรือ a namedtupleแทน แม้ว่าชั้นเรียนจะเป็นทางเลือกที่ดีที่สุดให้ใช้ ไพลินท์ไม่เคยรู้ว่าอะไรดีที่สุด
โปรดทราบว่าnamedtupleไม่เปลี่ยนรูปและค่าที่กำหนดในการสร้างอินสแตนซ์ไม่สามารถแก้ไขได้ในภายหลัง
dict namedtupleใช้คลาสเมื่อคุณต้องการเพิ่มตรรกะบางอย่างให้กับวัตถุของคุณ (ตัวอย่างเช่นคุณต้องการให้สิ่งต่างๆเกิดขึ้นเมื่อสร้างขึ้นคุณต้องการสิ่งพิเศษบางอย่างที่จะเกิดขึ้นเมื่อมีการเพิ่มคุณต้องการให้ดำเนินการบางอย่างกับมันควบคุมวิธีการ แสดง ฯลฯ )
namedtupleห่วย - นอกเหนือจากการมีไวยากรณ์ที่น่าเกลียดแล้วคุณไม่สามารถจัดทำเอกสารหรือระบุค่าเริ่มต้นได้อย่างง่ายดาย
namedtupleฉันเสียใจกับการตัดสินใจ ไม่สอดคล้องกันที่จะอนุญาตทั้งแอตทริบิวต์การเข้าถึงที่มีชื่อและแอตทริบิวต์การเข้าถึงที่จัดทำดัชนี
หากคุณกำลังขยายชั้นเรียนข้อเสนอแนะของฉันคือปิดการใช้งานคำเตือนนี้อย่างเป็นระบบและดำเนินการต่อเช่นในกรณีของงานขึ้นฉ่าย:
class MyTask(celery.Task): # pylint: disable=too-few-public-methods
"""base for My Celery tasks with common behaviors; extends celery.Task
...
แม้ว่าคุณจะขยายเพียงฟังก์ชันเดียว แต่คุณต้องมีคลาสเพื่อสร้างฟังก์ชันเทคนิคนี้และการขยายนั้นดีกว่าการแฮ็กคลาสของบุคคลที่สามอย่างแน่นอน!
min-public-methods=0ใน[BASIC]ส่วนของไฟล์กำหนดค่า สิ่งนี้ช่วยให้คุณวางไว้ในบรรทัดแยกต่างหากจากทุกdisable=สิ่งของคุณ(ใน[MESSAGE CONTROL]) ซึ่งฉันพบว่าทำให้การเพิ่มความคิดเห็นโดยละเอียดง่ายขึ้นเกี่ยวกับสาเหตุที่คุณเปิดใช้งานและปิดใช้งานสิ่งต่างๆพร้อมกับการเปลี่ยนแปลงการกำหนดค่า
นี่เป็นอีกกรณีหนึ่งของ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) และอื่น ๆ
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แต่ระวังตัวตั้งค่าอาจถือว่าฟิลด์อื่นได้รับการเตรียมใช้งานแล้วและคุณต้องมีการตรวจสอบความถูกต้องแบบกำหนดเองในตัวสร้าง) .
attrsไลบรารีซึ่งเป็นพิมพ์เขียวในการสร้างdataclassesโมดูล
namedtuplesมีไวยากรณ์แปลก ๆ สำหรับการสืบทอด ... ต้องการให้ทุกชั้นเรียนรู้ว่าเป็นทูเปิลที่มีชื่อและใช้__new__แทน__init__. dataclassesไม่มีข้อ จำกัด นี้
เป็นเรื่องยากเมื่อเจ้านายของคุณคาดหวังหลักการความรับผิดชอบเดียว แต่ไพลินท์บอกว่าไม่ ดังนั้นให้เพิ่มวิธีที่สองในชั้นเรียนของคุณเพื่อให้ชั้นเรียนของคุณละเมิดหลักการความรับผิดชอบเดียว คุณตั้งใจที่จะยึดหลักความรับผิดชอบเดียวแค่ไหนอยู่ในสายตาของผู้มอง
การแก้ไขของฉัน
ฉันได้เพิ่มวิธีการพิเศษในชั้นเรียนของฉันดังนั้นตอนนี้จึงมี 2 อย่าง
def __str__(self):
return self.__class__.__name__
ฉันแค่สงสัยว่าตอนนี้ฉันต้องแบ่งคลาสออกเป็น 2 ไฟล์แยกกันหรือไม่และอาจจะเป็นโมดูลด้วย
ปัญหาได้รับการแก้ไข แต่ไม่ใช่กับเพื่อนร่วมงานของฉันที่ใช้เวลาทั้งวันในการโต้เถียงเรื่องสเป็คแทนที่จะจัดการกับมันเหมือนชีวิตและความตาย