ฉันใช้ไพลินต์กับโค้ดบางโค้ดและได้รับข้อผิดพลาด "มีวิธีการสาธารณะน้อยเกินไป (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 ไฟล์แยกกันหรือไม่และอาจจะเป็นโมดูลด้วย
ปัญหาได้รับการแก้ไข แต่ไม่ใช่กับเพื่อนร่วมงานของฉันที่ใช้เวลาทั้งวันในการโต้เถียงเรื่องสเป็คแทนที่จะจัดการกับมันเหมือนชีวิตและความตาย