ทำไมพิชarmเสนอให้เปลี่ยนวิธีการเป็นแบบคงที่


154

pycharm รีลีสใหม่ (3.1.3 community edition) เสนอให้แปลงเมธอดที่ไม่ทำงานกับสถานะของวัตถุปัจจุบันเป็นสแตติก

ป้อนคำอธิบายรูปภาพที่นี่

อะไรคือเหตุผลที่ปฏิบัติได้จริง ประสิทธิภาพแบบไมโคร (- หรือ - หน่วยความจำ) - เพิ่มประสิทธิภาพบางอย่าง?


3
คุณคลิก "เพิ่มเติม ... " หรือไม่ คุณอ้างอิงselfที่ใดก็ได้ภายในวิธีการหรือไม่ (ถ้าคำถามจริงๆคือ "ทำไมนักออกแบบของ PyCharm จึงออกแบบมันด้วยวิธีนี้ ... คุณจะต้องถามพวกเขาไม่ใช่ SO ... )
Wooble

7
@ Wooble: มีreturn 1วิธีการใช้งานบรรทัดเดียว "เพิ่มเติม" ไม่มีสิ่งใดที่มีประโยชน์
zerkms

คำตอบ:


189

PyCharm "คิด" ที่คุณอาจต้องการมีวิธีการคงที่ แต่คุณลืมที่จะประกาศให้เป็นแบบคงที่ (ใช้@staticmethodมัณฑนากร)

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


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

1
อาจมีหลายกรณีที่คำเตือนของ PyCharm นั้นไม่ยุติธรรมเนื่องจากเราไม่ต้องการวิธีการคงที่หรือเปลี่ยนสถานะ NotImplementedErrorในทางตรงกันข้ามถ้าวิธีการที่ยังไม่ได้ใช้มันก็ดูเหมือนเสมอความคิดที่ดีที่จะเพิ่ม
jolvi

3
ผมมีกรณีที่การดำเนินการเริ่มต้นของฉันผลตอบแทนคงที่ แต่ subclasses selfของฉันได้รับอนุญาตให้กลับค่าขึ้นอยู่กับ ในกรณีนี้คำเตือน neglectable # noinspection PyMethodMayBeStaticและฉันทำเครื่องหมายด้วย เป็นเรื่องที่น่าผิดที่ IntelliJ IDEA ไม่ได้เสนอเพิ่มความคิดเห็นที่ปิดใช้งานในเมนูบริบทสำหรับคำเตือนนี้
Alfe

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

51

เห็นด้วยกับ @jolvi, @ArundasR และอื่น ๆ selfเตือนที่เกิดขึ้นในฟังก์ชันสมาชิกที่ไม่ได้ใช้

หากคุณแน่ใจว่า PyCharm ผิดฟังก์ชั่นนั้นไม่ควรเป็น@staticmethodและหากคุณให้คุณค่ากับคำเตือนที่เป็นศูนย์คุณสามารถทำให้สิ่งนี้หายไปได้สองวิธี:

วิธีแก้ปัญหา # 1

def bar(self):
    self.is_not_used()
    doing_something_without_self()

def is_not_used(self):
    pass

วิธีแก้ปัญหา # 2 [ขอบคุณ@ DavidPärsson ]

# noinspection PyMethodMayBeStatic
def bar(self):
    doing_something_without_self()

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

ในการสนับสนุนการตกตะลึงของ OP แนะนำให้คุณเพิ่มวิธีการคงที่ทุกครั้งที่คุณทำได้ขัดกับหลักการที่ทำให้การ จำกัด รหัสในภายหลังง่ายกว่าการทำเพิ่มเติม - การทำวิธีการแบบคงที่ทำให้ข้อ จำกัด น้อยลงในตอนนี้ เรียก class.f () แทน instance.f ()

คาดเดาสาเหตุที่มีคำเตือนนี้:

  • มันโฆษณาวิธีการคงที่ ทำให้นักพัฒนาตระหนักถึงสิ่งที่พวกเขาอาจตั้งใจไว้
  • ในฐานะที่เป็น @ คะแนนจาก JohnWorrall ของมันได้รับความสนใจของคุณเมื่อตัวเองถูกทิ้งไว้โดยไม่ได้ตั้งใจออกของฟังก์ชัน
  • มันเป็นคิวที่คิดใหม่โมเดลวัตถุ บางทีฟังก์ชั่นไม่ได้อยู่ในคลาสนี้เลย

1
"การสร้างเมธอดแบบสแตติกทำให้ตอนนี้มีข้อ จำกัด น้อยลง" --- มันไม่ได้เลย เช่น: วิธี polymorphic
zerkms

ฉันคิดว่าจุดสุดท้ายของการพูดซ้ำ: "ทำไมคุณถึงทำให้เป็นวิธีการเมื่อฟังก์ชั่นชัดเจน?" เก็บสิ่งต่าง ๆ ที่ต้องการอินสแตนซ์แยกต่างหากจากสิ่งโครงสร้างที่เกี่ยวข้องกับแง่มุมบางอย่าง จากนั้นคุณสามารถแบ่งมันออกเป็นโมดูลแยกได้อย่างง่ายดาย
dhill

@dhill Rules เป็นสิ่งที่สวยงามจนกระทั่งถึงวันที่คุณคิดว่ามีข้อยกเว้นที่สมเหตุสมผล ฉันอธิบายรายการโทรกลับหนึ่งรายการ
Bob Stein

7
การเพิ่ม# noinspection PyMethodMayBeStaticเมธอดหรือคลาสให้เหนือคำเตือนและอยู่ในความคิดของฉันดีกว่าเรียกวิธีที่ว่างเปล่า
David Pärsson

1
@Talha: selfไม่ถูกลบใน Python3 เลย
Junuxx

12

ฉันคิดว่าเหตุผลสำหรับการเตือนนี้คือการกำหนดค่าใน Pycharm คุณสามารถยกเลิกการเลือกวิธีการเลือกอาจคงที่ใน Editor-> Inspection


12
คำถามของฉันคือเหตุผลที่การตรวจสอบดังกล่าวยังคงมีอยู่ ฉันเข้าใจว่าฉันสามารถปิดได้ ขออภัยไม่ใช่คำตอบ
zerkms

9

ฉันเห็นด้วยกับคำตอบที่ได้รับที่นี่ (วิธีการใช้งานไม่ได้selfและดังนั้นจึงสามารถตกแต่งด้วย@staticmethod)

ฉันต้องการเพิ่มว่าคุณอาจต้องการย้ายวิธีการไปยังฟังก์ชั่นระดับบนสุดแทนวิธีคงที่ภายในชั้นเรียน สำหรับรายละเอียดดูคำถามนี้และคำตอบที่ยอมรับได้: หลามฉันควรใช้วิธีการคงที่หรือฟังก์ชั่นระดับบนสุด

การย้ายวิธีการไปยังฟังก์ชั่นระดับสูงสุดจะแก้ไขคำเตือน PyCharm ด้วย


คำตอบที่เป็นประโยชน์จริง ๆ - บางที PyCharm ควรเปลี่ยนชื่อคำเตือนเป็น 'เมธอดอาจเป็นฟังก์ชันคงที่หรือระดับบนสุด' เมื่อปรับเปลี่ยนวิธีการใหม่ pycharm จะสร้างฟังก์ชั่นระดับบนสุดและไม่ใช่วิธีการคงที่ถ้าselfไม่ใช่พารามิเตอร์
Suzana

@tlo +1 สำหรับการกล่าวถึงมัณฑนากร ฉันมีคลาสที่มีวิธีการที่ไม่ได้ใช้selfและอาจเป็นระดับบนสุดอย่างไรก็ตามนี่ไม่รู้สึกสมเหตุสมผลเมื่อมองว่าวิธีนี้ทำอะไร - เนื่องจากระดับบนสุดจะมองวิธีทั่วโลกมากกว่าในขณะที่มันเป็น ในความเป็นจริงเป็นวิธีช่วยเหลือเล็ก ๆ สำหรับอินสแตนซ์ที่สร้างจากคลาสนั้น ดังนั้นเพื่อให้รหัสของฉันจัดอย่างมีเหตุผลมัณฑนากรจึงเป็นโซลูชั่นที่สมบูรณ์แบบ
kasimir

7

ฉันสามารถจินตนาการถึงข้อดีของการมีวิธีการเรียนที่กำหนดเป็นแบบคงที่:

  • คุณสามารถเรียกใช้เมธอดได้โดยใช้ชื่อคลาสโดยไม่จำเป็นต้องสร้างอินสแตนซ์

ข้อได้เปรียบที่เหลืออยู่อาจเป็นเพียงเล็กน้อยหากมีอยู่:

  • อาจทำงานเร็วขึ้นเล็กน้อย
  • ประหยัดหน่วยความจำเล็กน้อย

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

1
@zerkms นี้เป็นวิธีที่มันจะไปกับกรณีที่มีเสน่ห์บาง :-)
ม.ค. Vlcinsky

2
วิธีการแบบคงที่เป็นศัตรูในการสร้างซอฟต์แวร์ที่ดี หลักการเหล่านี้ทำให้โมฆะbitทำงานได้เร็วขึ้นไม่ใช่สาเหตุ (ทำให้ RAM ทำงานได้เร็วในทั้งสองกรณี) และอย่างที่คุณรู้ว่าคอมพิวเตอร์มีbunchหน่วยความจำอยู่ในขณะนี้จึงไม่เป็นปัญหาอีกต่อไป โปรดสังเกตความคิดแรกของคุณ: นั่นเป็นพฤติกรรมขั้นตอนไม่ใช่วัตถุที่มุ่งเน้น
AmirHossein

4

เนื่องจากคุณไม่ได้อ้างถึงselfในbarเนื้อความของวิธีการ PyCharm จึงถามว่าคุณอาจต้องการทำให้barคงที่หรือไม่ ในภาษาการเขียนโปรแกรมอื่น ๆ เช่น Java มีเหตุผลที่ชัดเจนสำหรับการประกาศวิธีการคงที่ ใน Python ประโยชน์ที่แท้จริงเพียงอย่างเดียวของวิธีสแตติก (AFIK) สามารถเรียกใช้ได้โดยไม่มีอินสแตนซ์ของคลาส แต่ถ้านั่นคือเหตุผลเดียวที่คุณอาจจะดีกว่าไปกับฟังก์ชั่นระดับบน - เป็นโน้ตที่นี่

ในระยะสั้นฉันไม่แน่ใจร้อยเปอร์เซ็นต์ว่าทำไมถึงมี ฉันเดาว่าพวกเขาอาจจะลบมันในรุ่นที่กำลังจะมาถึง


3

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

my_player.attributes[item] 

แทนวิธีที่ถูกต้อง

self.attributes[item]

1

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

หากวิธีการของคุณมีผลข้างเคียงเพียงอย่างเดียวและคุณไม่สนใจว่าจะส่งคืนอย่างไร:

def bar(self):
    doing_something_without_self()
    return self

หากคุณต้องการค่าส่งคืน:

def bar(self):
    result = doing_something_without_self()
    if self:
        return result

ตอนนี้วิธีการของคุณกำลังใช้selfและคำเตือนหายไป!


0

เหตุผลที่ Pycharm ทำให้มันเป็นคำเตือนเพราะ Python จะส่งตัวเองเป็นอาร์กิวเมนต์แรกเมื่อเรียกใช้ไม่มีวิธีการคงที่ (ไม่เพิ่ม @ staticmethod) Pycharm รู้

ตัวอย่าง:

class T:
    def test():
        print "i am a normal method!"

t = T()
t.test()
output:
Traceback (most recent call last):
  File "F:/Workspace/test_script/test.py", line 28, in <module>
    T().test()
TypeError: test() takes no arguments (1 given)

ฉันมาจาก Java ใน Java "ตัวเอง" เรียกว่า "นี่" คุณไม่จำเป็นต้องเขียนตัวเอง (หรือนี่) เป็นอาร์กิวเมนต์ในวิธีการเรียน คุณสามารถเรียกตนเองได้ตามต้องการ แต่หลาม "ต้อง" ส่งต่อตัวเองเป็นอาร์กิวเมนต์วิธี

ด้วยการเข้าใจสิ่งนี้คุณไม่จำเป็นต้องมีวิธีแก้ปัญหาใด ๆ เหมือน @BobStein


มันผ่านไปselfเพื่ออะไร
zerkms

@zerkms '@staticmethod' ไม่ผ่าน 'self'
Junyu Wu

ฉันแค่อ้างถึงคุณ: "Python จะผ่านตัวเองเป็นอาร์กิวเมนต์แรก ... Pycharm รู้" แล้วอะไรล่ะ Pycharm รู้ฉันรู้แล้ว เหตุผลในการทำเครื่องหมายวิธีคืออะไร?
zerkms

@zerkms เนื่องจาก Pycharm คิดว่าวิธีการแรกของคุณอาจไม่ใช่ "ตัวตน" โดยทั่วไป ppl จะไม่ออกแบบวิธีการพารามิเตอร์และไม่เคยใช้มัน Pycharm คิดว่าคุณกำลังสร้างวิธีการคงที่และไม่ทราบว่าพารามิเตอร์แรกไม่ใช่ "ตัวเอง" ดังนั้นจึงเตือนโดยค่าเริ่มต้น ความสับสนนี้เกิดจากการออกแบบภาษาโปรแกรม ฉันขอแนะนำให้คุณทำตามการออกแบบการเขียนโปรแกรม (แม้ว่ามันจะไม่ใช่รูปแบบที่ดี) ให้เพิ่ม "staticmethod" เพื่อหลีกเลี่ยงความสับสน มันดีมากถ้าคุณเพิ่ม "ตนเอง" จากนั้นอย่าใช้มันหากคุณต้องการ สิ่งที่ฉันพูดเป็นเพียงความแตกต่างโดยเข้าใจการออกแบบการเขียนโปรแกรม
Junyu Wu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.