วิธีการคงที่ - จะเรียกวิธีการจากวิธีอื่นได้อย่างไร?


100

เมื่อฉันมีเมธอดปกติในการเรียกเมธอดอื่นในคลาสฉันต้องทำสิ่งนี้

class test:
    def __init__(self):
        pass
    def dosomething(self):
        print "do something"
        self.dosomethingelse()
    def dosomethingelse(self):
        print "do something else"

แต่เมื่อฉันมีวิธีคงที่ฉันไม่สามารถเขียนได้

self.dosomethingelse()

เนื่องจากไม่มีอินสแตนซ์ ฉันต้องทำอย่างไรใน Python เพื่อเรียก Static Method จาก Static Method อื่นของคลาสเดียวกัน

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


3
@pablo: เปลี่ยนสาระสำคัญของคำถามไม่ได้ !! จบคำถามนี้แล้วเริ่มกันใหม่ !!
jldupont

โอเคโอเค. คุณหมายถึงลบคำถามใช่ไหม คำตอบมีอยู่แล้วในความคิดเห็นของ Peter Hansen
Pablo

@pablo: คุณไม่สามารถลบที่นี่ซึ่งจะไม่สุภาพสำหรับทุกคนที่ให้คำตอบสำหรับคำถามของคุณ คุณต้องยอมรับคำตอบและสร้างคำถามใหม่
jldupont

1
@pablo: และเพื่อให้ชัดเจน: ควรยอมรับคำตอบสำหรับการกำหนดคำถามเดิมของคุณ ไม่ต้องกังวลคุณจะได้เรียนรู้เส้นทางของคุณที่นี่ ไชโย :-)
jldupont

คำตอบ:


80

class.method ควรทำงาน.

class SomeClass:
  @classmethod
  def some_class_method(cls):
    pass

  @staticmethod
  def some_static_method():
    pass

SomeClass.some_class_method()
SomeClass.some_static_method()

17
ควรเพิ่มคำแนะนำที่นี่: เป็นที่ชัดเจนว่า classmethods ไม่มีข้อบกพร่องในเรื่อง staticmethods และ classmethods อนุญาตให้ขยาย method ในอนาคตเพื่อเรียก class method อื่น ๆ ดังนั้นจึงควรเป็นที่ต้องการแม้ว่าจะไม่มีความจำเป็นในทันทีก็ตาม
u0b34a0f6ae

1
@ u0b34a0f6ae: ฉันไม่รู้ว่าฉันทำอะไรดีหรือเปล่า ... แต่ฉันกำหนดมัณฑนากรไว้ในชั้นเรียน มัณฑนากรต้องเป็น "staticmethod" ไม่ใช่ "classmethod"
André Caldas

@ u0b34a0f6ae วิธีการคลาสเสมอเธรดปลอดภัยหรือไม่? ในกรณีการใช้งานของฉันฉันกำลังใช้วิธีการคงที่ในเธรดเพื่อป้องกันการเข้าถึงคลาสโดยไม่ได้ตั้งใจซึ่งอาจไม่ปลอดภัยสำหรับเธรด
aquavitae

@ u0b34a0f6ae แรงไปหน่อยเสมอ ตัวอย่างเช่นการใช้ PySpark staticmethods สามารถใช้ในงาน rdd และ classmethods ไม่สามารถใช้ได้
Laurens Koppenol

143

ฉันต้องทำอย่างไรใน Python เพื่อเรียก Static Method จาก Static Method อื่นของคลาสเดียวกัน

class Test() :
    @staticmethod
    def static_method_to_call()
        pass

    @staticmethod
    def another_static_method() :
        Test.static_method_to_call()

    @classmethod
    def another_class_method(cls) :
        cls.static_method_to_call()

การโทรTest.static_method_to_call()ควรทำงานจากเมธอดอื่นที่ไม่คงที่และไม่ใช่คลาสของคลาสนี้ด้วยใช่ไหม (... และอาจจะเรียนอื่น ๆ ด้วย?)
gr4nt3d

ใช่Test.static_method_to_call()จะทำงานได้จากทุกที่
warvariuc

11

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

สิ่งต่อไปนี้คือคำตอบส่วนใหญ่ "คุณเรียกวิธีการแบบคงที่จากวิธีการคงที่อื่นได้อย่างไร":

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

หากเป็นวิธีคงที่:

test.dosomethingelse()

หากเป็นวิธีการเรียน:

cls.dosomethingelse()

1
คุณสามารถใช้ได้cls.dosomethingelse()จากภายในนิยามคลาสเท่านั้น
jldupont

3
เพื่อให้แม่นยำยิ่งขึ้นคุณสามารถใช้ได้cls.dosomethingelse()จากในเมธอดคลาสเท่านั้น เช่นเดียวกับที่คุณสามารถใช้ได้selfจากภายในวิธีการอินสแตนซ์เท่านั้น
Jason Baker

1
ขอโทษฉันเขียนคำถามผิด โอ๊ะ! ฉันต้องการเขียนว่า "ฉันต้องทำอย่างไรใน Python เพื่อเรียกวิธีการอินสแตนซ์จากวิธีการคงที่อื่นในคลาสเดียวกัน" และไม่ใช่ "ฉันต้องทำอย่างไรใน Python เพื่อเรียกวิธีการแบบคงที่จากวิธีการคงที่อื่นที่เหมือนกัน class "
Pablo

@pablo: ในกรณีนี้คุณต้องเขียนคำถามอีกข้อและจบคำถามนี้
jldupont

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

4

ตกลงความแตกต่างหลักระหว่าง class method และ static method คือ:

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

ดูเหมือนจะไม่ถูกต้อง - แต่ความหมายในที่นี้คลุมเครือหากไม่มีตัวอย่างจึงยากที่จะบอกได้ โดยหลักแล้ว "class method" ไม่จำเป็นต้องถูกเรียกว่า "จากในอินสแตนซ์" ... คุณสามารถโทรได้MyClass.class_method()จากทุกที่ที่รู้เรื่องMyClass(บางทีคุณอาจกำลังคิดถึง "วิธีการอินสแตนซ์"?)
mltsy

1

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

เนื่องจากคำตอบที่ถูกต้องจะขึ้นอยู่กับกรณีการใช้งานของรหัสที่เป็นปัญหา;) สนุก


0

คุณไม่สามารถเรียกวิธีการที่ไม่คงที่จากวิธีการคงที่ แต่โดยการสร้างอินสแตนซ์ภายในวิธีการคงที่ .... มันควรจะทำงานเช่นนั้น

class test2(object):
    def __init__(self):
        pass

    @staticmethod
    def dosomething():
        print "do something"
        #creating an instance to be able to call dosomethingelse(),or you may use any existing instace
        a=test2()
        a.dosomethingelse()

    def dosomethingelse(self):
        print "do something else"

test2.dosomething()

หวังว่าจะช่วยคุณได้ :)


3
IMO วิธีนี้แย่กว่าการใช้@classmethodเพื่อประกาศวิธีการของคุณและการใช้cls.dosomethingelse()ภายในcls.dosomething()- แย่กว่าในแง่ของประสิทธิภาพทั้งสอง (การสร้างอินสแตนซ์อ็อบเจ็กต์เพื่อเข้าถึงวิธีการคงที่) และความสามารถในการอ่าน (มันไม่ตรงไปตรงมาและฉันคิดว่าถ้าประเภทนั้น ของรูปแบบกลายเป็นต้นแบบโค้ดเบสทั้งหมดอาจกลายเป็นเรื่องยากสำหรับมนุษย์ที่จะแยกวิเคราะห์)
Kyle Wild

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