ข้อดีของการใช้วิธีการคงที่ใน Python คืออะไร?


90

ฉันพบข้อผิดพลาดวิธี unbound ใน python พร้อมรหัส

import random

class Sample(object):
'''This class defines various methods related to the sample'''

    def drawSample(samplesize,List):
        sample=random.sample(List,samplesize)
        return sample

Choices=range(100)
print Sample.drawSample(5,Choices)

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


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

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

3
@ S.Lott: เมื่อใดที่การใช้วิธีสถิตเป็นสิ่งจำเป็นเมื่อเทียบกับการใช้วิธีคลาสปกติ เท่าที่ฉันสามารถบอกได้เมธอดคลาสสามารถทำทุกอย่างที่วิธีการคงที่สามารถทำได้ Staticmethod มี "ข้อดี" ตามที่ระบุไว้ที่อื่นในโพสต์นี้ แต่ฉันไม่เห็นเหตุผลใด ๆ ที่ไม่สามารถใช้เมธอดคลาสในสถานที่ใด ๆ ที่สามารถใช้วิธีการแบบคงที่ได้ดังนั้นจึงมีความจำเป็น
RFV

คำตอบ:


130

วิธีการแบบคงที่มีการใช้งานที่ จำกัด เนื่องจากไม่สามารถเข้าถึงแอตทริบิวต์ของอินสแตนซ์ของคลาสได้ (เช่นเดียวกับวิธีการทั่วไป) และไม่สามารถเข้าถึงแอตทริบิวต์ของคลาสได้ (เช่นเดียวกับวิธีคลาส ).

ดังนั้นจึงไม่มีประโยชน์สำหรับวิธีการแบบวันต่อวัน

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

สามารถวางไว้นอกชั้นเรียนได้ แต่การจัดกลุ่มไว้ในชั้นเรียนอาจทำให้เข้าใจได้ว่าจะใช้ได้เฉพาะที่นั่นเท่านั้น

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


9
@ Curious2learn: ไม่ใช่ทุกวิธีแต่บางวิธีมีประโยชน์ในฐานะวิธีการคงที่ ลองนึกถึงLocaleคลาสตัวอย่างซึ่งอินสแตนซ์จะเป็นโลแคล (duh) getAvailableLocales()วิธีการจะเป็นตัวอย่างที่ดีของวิธีการคงของชั้นดังกล่าวอย่างชัดเจนอยู่ในระดับสถานที่เกิดเหตุในขณะที่ยังเห็นได้ชัดไม่ได้เป็นเช่นใดโดยเฉพาะ
MestreLion

1
... และมันก็ไม่ใช่เมธอดคลาสเช่นกันเนื่องจากอาจไม่จำเป็นต้องเข้าถึงเมธอดของคลาสใด ๆ
MestreLion

1
ชี้ให้เห็นว่าการแก้ไขวิธีการคงสามารถเข้าถึงคุณลักษณะระดับโดยชัดเจนการนำลงมาจากclass_name.attributeเพียงแค่ไม่ได้หรือcls.attribute self.attributeซึ่งเป็นจริงสำหรับแอตทริบิวต์ "สาธารณะ" ตามแบบแผนคุณไม่ควรเข้าถึงแอตทริบิวต์ที่ซ่อนด้วยเครื่องหมายขีดล่างหรือชื่อที่ยุ่งเหยิงด้วยขีดล่างสองอันด้วยวิธีนี้ นอกจากนี้ยังหมายความว่าโค้ดของคุณจะเปราะบางมากขึ้นเมื่อแอตทริบิวต์เปลี่ยนตำแหน่งบนลำดับชั้นการสืบทอด
Oddthinking

1
คำพูดจาก Guido ที่ช่วยในการตัดสินใจว่าเมื่อใดควรใช้วิธีการคงที่ (ไม่เคย): "เราทุกคนรู้ดีว่าวิธีการคงที่ จำกัด เป็นอย่างไร (โดยพื้นฐานแล้วเป็นอุบัติเหตุ - ย้อนกลับไปใน Python 2.2 วันที่ฉันกำลังประดิษฐ์คลาสและตัวอธิบายรูปแบบใหม่ ฉันตั้งใจจะใช้เมธอดคลาส แต่ตอนแรกฉันไม่เข้าใจและใช้วิธีการแบบคงที่โดยไม่ได้ตั้งใจก่อนจากนั้นก็สายเกินไปที่จะลบออกและให้เฉพาะเมธอดคลาสเท่านั้น "
บอริสชูร์ซิน

192

ดูบทความนี้สำหรับคำอธิบายโดยละเอียด

TL; ดร

1. ช่วยลดการใช้selfอาร์กิวเมนต์

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

>>>RandomClass().regular_method is RandomClass().regular_method
False
>>>RandomClass().static_method is RandomClass().static_method
True
>>>RandomClass.static_method is RandomClass().static_method
True

3. ช่วยเพิ่มความสามารถในการอ่านโค้ดซึ่งแสดงว่าเมธอดไม่ได้ขึ้นอยู่กับสถานะของอ็อบเจ็กต์

4. ช่วยให้สามารถแทนที่เมธอดในกรณีที่กำหนดเมธอดในระดับโมดูล (เช่นนอกคลาส) คลาสย่อยจะไม่สามารถแทนที่เมธอดนั้นได้


3
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ ความจริงที่ว่าวิธีการแบบคงที่ในอินสแตนซ์ใด ๆ และคลาสนั้นเป็นออบเจ็กต์เดียวกันนั้นเป็นข้อได้เปรียบที่แท้จริงโดยเฉพาะอย่างยิ่งเมื่อคุณมีอินสแตนซ์จำนวนมาก (เช่นแต่ละอินสแตนซ์สำหรับบันทึกฐานข้อมูลที่ไม่แน่นอน)
Zhuoyun Wei

1
+1 และเห็นด้วยกับ @ZhuoyunWei เฉพาะคำตอบที่อธิบายเหตุผลบางประการที่บางครั้งวิธีการคงที่เป็นที่นิยมกว่าวิธีการคลาส (แม้ว่า 1 และ 3 เป็นเหตุผลเดียวกันก็ตาม)
Alex

2
คำตอบที่ดีที่สุดสำหรับ "ทำไมต้องใช้วิธีคงที่" แต่คำถามเดิมยังถามว่า "ทำไมทุกวิธีจึงไม่คงที่ "ไม่สามารถเข้าถึงแอตทริบิวต์อินสแตนซ์" แบบสั้น ๆ ก็ครอบคลุมเช่นกัน
Exu

1
ข้อได้เปรียบที่แท้จริงเพียงอย่างเดียวของ IMO คือคุณสามารถแทนที่มันในคลาสย่อยได้ แต่ถึงอย่างนั้นก็มีความรู้สึกว่าคุณกำลังทำอะไรผิดพลาด OOP ฉลาดคุณจะทำเช่นนั้นในกรณีใด
Boris Churzin

1
3. - ถ้าไม่มีสถานะทำไมต้องสร้างคลาสตั้งแต่แรก? ฟังก์ชันโมดูลจะดีพอ ๆ กันโดยมีโค้ดน้อยลง
Alex

23

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

ฉันจะไม่แก้ไขรหัสข้างต้นโดยทำให้วิธีการเป็นวิธีคงที่ ฉันอาจจะเลิกเรียนและเขียนฟังก์ชัน:

def drawSample(samplesize,List):
    sample=random.sample(List,samplesize)
    return sample

Choices=range(100)
print drawSample(5,Choices)

หากคุณมีฟังก์ชันที่เกี่ยวข้องจำนวนมากคุณสามารถจัดกลุ่มไว้ในโมดูล - กล่าวคือวางทั้งหมดไว้ในไฟล์เดียวกันโดยตั้งชื่อsample.pyเช่น แล้ว

import sample

Choices=range(100)
print sample.drawSample(5,Choices)

หรือฉันจะเพิ่ม__init__วิธีการในคลาสและสร้างอินสแตนซ์ที่มีวิธีการที่มีประโยชน์:

class Sample(object):
'''This class defines various methods related to the sample'''

    def __init__(self, thelist):
        self.list = thelist

    def draw_sample(self, samplesize):
        sample=random.sample(self.list,samplesize)
        return sample

choices=Sample(range(100))
print choices.draw_sample(5)

(ฉันยังเปลี่ยนรูปแบบเคสในตัวอย่างด้านบนเพื่อให้ตรงกับสไตล์ที่แนะนำโดย PEP 8)

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


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

4
+1: นั่นเป็นคำอธิบายที่ดีสำหรับความเข้าใจผิดบางอย่างที่ OP มี และคุณพูดตรงไปตรงมาอย่างตรงไปตรงมาว่าคุณไม่ได้ตอบคำถามของเขาเกี่ยวกับวิธีการคงที่ แต่คุณให้คำตอบที่ดีกว่ามากโดยบอกว่าปัญหาของเขาไม่จำเป็นต้องมีชั้นเรียนเลย
MestreLion

22

ทำไมเราถึงต้องการกำหนดวิธีการแบบคงที่ ?

สมมติว่าเราclassโทรMathมาแล้ว

ไม่มีใครจะต้องการที่จะสร้างวัตถุของclass Math
แล้วเรียกวิธีการเช่นceilและfloorและfabsอยู่กับมัน

ดังนั้นเราจึงสร้างมันstaticขึ้นมา

ตัวอย่างเช่นการทำ

>> Math.floor(3.14)

ดีกว่ามาก

>> mymath = Math()
>> mymath.floor(3.14)

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

ทำไมไม่ได้เป็นวิธีการทั้งหมดกำหนดเป็นวิธีการคง ?

พวกเขาไม่มีสิทธิ์เข้าถึงตัวแปรอินสแตนซ์

class Foo(object):
    def __init__(self):
        self.bar = 'bar'

    def too(self):
        print self.bar

    @staticmethod
    def foo():
        print self.bar

Foo().too() # works
Foo.foo() # doesn't work

นั่นคือเหตุผลที่เราไม่ทำให้วิธีการทั้งหมดคงที่


10
แต่ทำไมไม่เป็นคณิตศาสตร์แบบแพ็คเกจล่ะ? Python มีแพ็คเกจสำหรับสิ่งนั้นคุณไม่จำเป็นต้องมีการกำหนดคลาสเพื่อสร้างเนมสเปซ
ภายนอก

6
@extraneon: Yup เพื่อนฉันรู้ว่า Mathแต่ฉันต้องการที่จะมีสิ่งที่ง่ายและคุ้นเคยสำหรับคำอธิบายดังนั้นผมจึงใช้ Mนั่นคือเหตุผลที่ผมนิยาม
Pratik Deoghare

6
OP ไม่ได้ถามว่าวิธีการคงที่คืออะไร เขาถามว่าประโยชน์ของพวกเขาคืออะไร คุณกำลังอธิบายวิธีใช้ไม่ใช่ว่ามีประโยชน์อย่างไร ในตัวอย่างเฉพาะของคุณเนมสเปซจะเหมาะสมกว่ามาก
Javier

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

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

15

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

เมื่อคุณเรียกclassmethodอ็อบเจ็กต์ (ซึ่งปิดอ็อบเจ็กต์ฟังก์ชัน) บนอินสแตนซ์อ็อบเจ็กต์คลาสของอ็อบเจ็กต์อินสแตนซ์จะถูกส่งผ่านเป็นอาร์กิวเมนต์แรก

เมื่อคุณเรียกstaticmethodวัตถุ (ซึ่งล้อมรอบวัตถุฟังก์ชัน) จะไม่มีการใช้อาร์กิวเมนต์แรกโดยนัย

class Foo(object):

    def bar(*args):
        print args

    @classmethod
    def baaz(*args):
        print args

    @staticmethod
    def quux(*args):
        print args

>>> foo = Foo()

>>> Foo.bar(1,2,3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got int instance instead)
>>> Foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> Foo.quux(1,2,3)
(1, 2, 3)

>>> foo.bar(1,2,3)
(<Foo object at 0x1004a4510>, 1, 2, 3)
>>> foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> foo.quux(1,2,3)
(1, 2, 3)

3
+1: ในที่สุดคำอธิบายที่ดีเกี่ยวกับวิธีการคงที่และวิธีการคลาสคืออะไร แม้ว่าคุณจะไม่ได้อธิบายว่าทำไมใครเคยต้องการที่จะใช้วิธีการแบบคงที่อย่างน้อยคุณอธิบายอย่างชัดเจนในตัวอย่างง่ายๆสิ่งที่ทั้งสองมีมากดีกว่าเอกสารอย่างเป็นทางการไม่
MestreLion

5

ทางเลือกในการให้staticmethodคือclassmethod, และinstancemethod functionหากคุณไม่ทราบว่าสิ่งเหล่านี้คืออะไรให้เลื่อนลงไปที่ส่วนสุดท้าย หาก a staticmethodดีกว่าทางเลือกใด ๆ เหล่านี้ขึ้นอยู่กับวัตถุประสงค์ที่เขียนขึ้น

ข้อดีของ Python static method

  • ถ้าคุณไม่จำเป็นต้องเข้าถึงคุณลักษณะหรือวิธีการเรียนหรืออินสแตนซ์ที่เป็นstaticmethodดีกว่าหรือclassmethod instancemethodด้วยวิธีนี้เป็นที่ชัดเจน (จาก@staticmethodมัณฑนากร) ว่าสถานะของคลาสและอินสแตนซ์ไม่ได้ถูกอ่านหรือแก้ไข อย่างไรก็ตามการใช้การfunctionทำให้ความแตกต่างนั้นชัดเจนยิ่งขึ้น (ดูข้อเสีย)
  • ลายเซ็นโทรของstaticmethodเป็นเช่นเดียวกับที่ของclassmethodหรือคือinstancemethod <instance>.<method>(<arguments>)ดังนั้นจึงสามารถแทนที่ได้อย่างง่ายดายด้วยหนึ่งในสามหากจำเป็นในภายหลังหรือในคลาสที่ได้รับ functionคุณไม่สามารถทำเช่นนั้นกับที่เรียบง่าย
  • A staticmethodสามารถใช้แทน a functionเพื่อให้ชัดเจนว่าเป็นของคลาสและเพื่อป้องกันความขัดแย้งของเนมสเปซ

ข้อเสียของวิธีการคงที่ของ Python

  • ไม่สามารถเข้าถึงแอตทริบิวต์หรือวิธีการของอินสแตนซ์หรือคลาส
  • ลายเซ็นโทรของstaticmethodเป็นเช่นเดียวกับที่ของหรือclassmethod instancemethodสิ่งนี้ปิดบังความจริงที่staticmethodว่าไม่ได้อ่านหรือแก้ไขข้อมูลวัตถุใด ๆ ทำให้โค้ดอ่านยากขึ้น ทำไมไม่ใช้ a function?
  • A staticmethodใช้ซ้ำได้ยากหากคุณจำเป็นต้องเรียกใช้จากภายนอกคลาส / อินสแตนซ์ที่กำหนดไว้ หากมีความเป็นไปได้ในการใช้ซ้ำ a functionเป็นทางเลือกที่ดีกว่า
  • staticmethodไม่ค่อยมีใครใช้เพื่อให้คนที่มีรหัสหนึ่งอาจใช้เวลาอีกหน่อยจะอ่านมันอ่าน

ทางเลือกแทนวิธีคงที่ใน Python

เพื่อหารือเกี่ยวกับข้อดีของข้อได้เปรียบstaticmethodเราจำเป็นต้องทราบว่าทางเลือกอื่นคืออะไรและแตกต่างกันอย่างไร

  • staticmethodอยู่ในชั้นเรียน แต่ไม่สามารถเข้าถึงหรือแก้ไขอินสแตนซ์หรือระดับข้อมูลใด ๆ

มีสามทางเลือกให้:

  • classmethodมีการเข้าถึงชั้นที่โทรมา
  • instancemethodมีการเข้าถึงเช่นโทรและที่ระดับ
  • functionมีอะไรจะทำอย่างไรกับการเรียน เป็นความสามารถที่ใกล้เคียงที่สุดกับไฟล์staticmethod.

นี่คือสิ่งที่ดูเหมือนในโค้ด:

# function
# has nothing to do with a class
def make_cat_noise(asker_name):
    print('Hi %s, mieets mieets!' % asker_name)

# Yey, we can make cat noises before we've even defined what a cat is!
make_cat_noise('JOey')  # just a function

class Cat:
    number_of_legs = 4

    # special instance method __init__
    def __init__(self, name):
        self.name = name

    # instancemethod
    # the instance (e.g. Cat('Kitty')) is passed as the first method argument
    def tell_me_about_this_animal(self, asker_name):
        print('Hi %s, This cat has %d legs and is called %s'
              % (asker_name, self.number_of_legs, self.name))

    # classmethod
    # the class (e.g. Cat) is passed as the first method argument
    # by convention we call that argument cls
    @classmethod
    def tell_me_about_cats(cls, asker_name):
        print("Hi %s, cats have %d legs."
              % (asker_name, cls.number_of_legs))
        # cls.name  # AttributeError because only the instance has .name
        # self.name  # NameError because self isn't defined in this namespace

    # staticmethod
    # no information about the class or the instance is passed to the method
    @staticmethod
    def make_noise(asker_name):
        print('Hi %s, meooow!' % asker_name)
        # class and instance are not accessible from here

# one more time for fun!
make_cat_noise('JOey')  # just a function

# We just need the class to call a classmethod or staticmethod:
Cat.make_noise('JOey')  # staticmethod
Cat.tell_me_about_cats('JOey')  # classmethod
# Cat.tell_me_about_this_animal('JOey')  # instancemethod -> TypeError

# With an instance we can use instancemethod, classmethod or staticmethod
mycat = Cat('Kitty')  # mycat is an instance of the class Cat
mycat.make_noise('JOey')  # staticmethod
mycat.tell_me_about_cats('JOey')  # classmethod
mycat.tell_me_about_this_animal('JOey')  # instancemethod

3

วิธีการแบบคงที่ดีมากเพราะคุณไม่จำเป็นต้องประกาศอินสแตนซ์ของอ็อบเจ็กต์ที่เป็นของเมธอด

เว็บไซต์ของ python มีเอกสารที่ยอดเยี่ยมเกี่ยวกับวิธีการแบบคงที่ที่นี่:
http://docs.python.org/library/functions.html#staticmethod


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

4
@ Curious2learn: ไม่ด้วยเมธอดแบบคงที่คุณไม่มีสิทธิ์เข้าถึงอินสแตนซ์: อินสแตนซ์จะถูกละเว้นยกเว้นคลาส
Felix Kling

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

1
@extraneon - นั่นเป็นเรื่องของการตั้งค่าองค์กรรหัสมากกว่า การมีวิธีการแบบคงที่ทำให้มีตัวเลือกพิเศษ
Charles Duffy

@Felix - ขอบคุณ นี่เป็นการชี้แจงว่าเหตุใดทุกวิธีจึงไม่ควรเป็นวิธีคงที่
Curious2learn

1

วิธีการคงที่แทบไม่มีเหตุผลที่จะเป็นใน Python คุณใช้วิธีการอินสแตนซ์หรือวิธีคลาส

def method(self, args):
    self.member = something

@classmethod
def method(cls, args):
    cls.member = something

@staticmethod
def method(args):
    MyClass.member = something
    # The above isn't really working
    # if you have a subclass

คุณบอกว่า "เกือบ" มีสถานที่ที่พวกเขาจะดีกว่าทางเลือกอื่นหรือไม่?
Javier

@Javier: ฉันคิดไม่ออก แต่อาจมีอยู่ทำไมวิธีนั้นถึงรวมอยู่ในไลบรารี Python เป็นอย่างอื่น
Georg Schölly

1
@Javier, @Georg: คุณมีความเชื่ออย่างยิ่งว่า Python corpus ไม่ได้มีการตรึง
Charles Merriam

-1: คำตอบนี้ไม่ได้นำเสนอใด ๆกรณีการใช้staticmethodหรือใด ๆคำอธิบายของสิ่งที่classmethodเป็นหรือทำไมและวิธีการที่จะ "ดี" กว่าคนคง
MestreLion

@CharlesMerriam: แน่นอนว่าวิธีการแบบคงที่มีการใช้งานไม่เช่นนั้นจะถูกทิ้งหรือเลิกใช้ใน Python 3 (ซึ่งส่วนใหญ่ของ cruft ดั้งเดิมถูกลบออก) ไม่มีคำใดคำหนึ่งที่ต่อต้านstaticmethodในเอกสารเพื่อสนับสนุนการอ้างสิทธิ์ของคุณว่าเป็นสิ่งที่สำคัญที่สุดหรือคำกล่าวอ้างของเฟรดที่classmethodควรใช้แทน)
MestreLion

1

เนื่องจากฟังก์ชั่นเนมสเปซนั้นดี (ตามที่เคยระบุไว้ก่อนหน้านี้):

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

  2. เมื่อฉัน refactor รหัสเน่าจริงๆฉันเริ่มต้นด้วยการพยายามสร้างวิธีการต่างๆ@staticmethodให้ได้มากที่สุด สิ่งนี้ทำให้ฉันสามารถแยกวิธีการเหล่านี้ลงในชั้นเรียนได้ - แม้ว่าฉันจะเห็นด้วยก็ตามนี่ไม่ใช่สิ่งที่ฉันใช้ แต่ก็มีประโยชน์ไม่กี่ครั้ง


1

ในการประมาณค่าของฉันไม่มีประโยชน์ด้านประสิทธิภาพเพียงอย่างเดียวของการใช้@staticmethods เมื่อเทียบกับการกำหนดฟังก์ชันภายนอกและแยกจากคลาสเท่านั้นมิฉะนั้นจะเป็น a @staticmethodของ

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

สิ่งหนึ่งที่ผมบางครั้งต้องการจะทำคือการทำงานสถานที่ที่ใช้ชั้นเรียนของฉันภายในเป็นจำนวนมากเข้าไปในส่วนตัว@staticmethods ด้วยวิธีนี้ฉันจะไม่เกะกะ API ที่โมดูลของฉันเปิดเผยด้วยวิธีการที่ไม่มีใครที่ใช้โมดูลของฉันต้องเห็นนับประสาใช้

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