"staticmethod" และ "abc.abstractmethod`: จะผสมผสานกันหรือไม่?


108

ในแอพ Python ของฉันฉันต้องการสร้างเมธอดที่เป็นทั้ง a staticmethodและabc.abstractmethod. ฉันต้องทำอย่างไร

ฉันลองใช้มัณฑนากรทั้งสอง แต่ไม่ได้ผล ถ้าฉันทำสิ่งนี้:

import abc

class C(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    @staticmethod    
    def my_function(): pass

ฉันได้รับข้อยกเว้น * และถ้าฉันทำสิ่งนี้:

class C(object):
    __metaclass__ = abc.ABCMeta

    @staticmethod    
    @abc.abstractmethod
    def my_function(): pass

ไม่มีการบังคับใช้วิธีนามธรรม

ฉันจะสร้างวิธีการคงที่แบบนามธรรมได้อย่างไร

* ข้อยกเว้น:

File "c:\Python26\Lib\abc.py", line 29, in abstractmethod
 funcobj.__isabstractmethod__ = True
AttributeError: 'staticmethod' object has no attribute '__isabstractmethod__'

5
โปรดอัปเดตคำตอบที่คุณยอมรับ
Neil G

คำตอบ:


35
class abstractstatic(staticmethod):
    __slots__ = ()
    def __init__(self, function):
        super(abstractstatic, self).__init__(function)
        function.__isabstractmethod__ = True
    __isabstractmethod__ = True

class A(object):
    __metaclass__ = abc.ABCMeta
    @abstractstatic
    def test():
        print 5

7
เล่นดีครับท่านหรือท่านผู้หญิง :-) คุณทิ้งไว้import abcที่ด้านบน เช่นเดียวกับคลาสย่อยที่แสดงการสร้างอินสแตนซ์ของ A. (เช่นclass B(A):\n @staticmethod\n def test():\n print 10\n)
Dan Breslau

1
ฉันอัปเดตโค้ดเพื่อให้ทำงานได้อย่างถูกต้องกับคลาสย่อย A. การทดสอบควรมี__isabstractmethod__แอตทริบิวต์
Rosh Oxymoron

3
ควรabstractstaticเพิ่มต้นน้ำเพื่อabc.py?
nnyby

3
abstractstaticmethod เลิกใช้งานตั้งแต่เวอร์ชัน 3.3: ขณะนี้สามารถใช้ staticmethod กับ abstractmethod () ได้ทำให้มัณฑนากรนี้ซ้ำซ้อน ลิงค์
irakli khitarishvili

1
@iraklikhitarishvili ยังคงไม่บังคับว่าวิธีการของคลาสย่อยจะคงที่! คุณต้องทำซ้ำมัณฑนากรแบบคงที่ ... ไม่มีทางทำได้เหรอ?
étale-cohomology

206

เริ่มต้นด้วยPython 3.3เป็นไปได้ที่จะรวม @staticmethodและ@abstractmethodดังนั้นจึงไม่จำเป็นต้องมีคำแนะนำอื่น ๆ อีกต่อไป:

@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):

36
โปรดทราบว่าคุณต้องใส่@staticmethodเป็นอันดับแรกมิฉะนั้นคุณจะได้รับAttributeError: attribute '__isabstractmethod__' of 'staticmethod' objects is not writable
Marco Sulla

3
เหมือนกันสำหรับ@property
zezollo

12
มันจะมีประโยชน์มากถ้านี่เป็นคำตอบที่ได้รับการยอมรับ!
Keerthana Prabhakaran

สิ่งที่ฉันกำลังมองหา ขอบคุณ!
shanu khera

13

สิ่งนี้จะทำ:

  >>> import abc
  >>> abstractstaticmethod = abc.abstractmethod
  >>>
  >>> class A(object):
  ...     __metaclass__ = abc.ABCMeta
  ...     @abstractstaticmethod
  ...     def themethod():
  ...          pass
  ... 
  >>> a = A()
  >>> Traceback (most recent call last):
  File "asm.py", line 16, in <module>
    a = A()
  TypeError: Can't instantiate abstract class A with abstract methods test

คุณไป "เอ๊ะมันเปลี่ยนชื่อเป็น @abstractmethod" แค่นี้ก็ถูกต้องแล้ว เนื่องจากคลาสย่อยใด ๆ ข้างต้นจะต้องรวมมัณฑนากร @staticmethod ไว้ด้วย คุณไม่จำเป็นต้องใช้ที่นี่ยกเว้นเป็นเอกสารประกอบเมื่ออ่านรหัส คลาสย่อยจะต้องมีลักษณะดังนี้:

  >>> class B(A):
  ...     @staticmethod
  ...     def themethod():
  ...         print "Do whatevs"

หากต้องการมีฟังก์ชันที่บังคับให้คุณทำให้วิธีนี้เป็นวิธีการคงที่คุณจะต้องซับคลาส ABCmeta เพื่อตรวจสอบและบังคับใช้ นั่นเป็นงานมากมายที่ไม่มีผลตอบแทนที่แท้จริง (หากมีใครลืมมัณฑนากร @staticmethod พวกเขาจะได้รับข้อผิดพลาดที่ชัดเจนอย่างไรก็ตามจะไม่กล่าวถึงวิธีการคงที่

ดังนั้นในความเป็นจริงมันก็ใช้ได้เช่นกัน:

  >>> import abc
  >>>
  >>> class A(object):
  ...     __metaclass__ = abc.ABCMeta
  ...     @abc.abstractmethod
  ...     def themethod():
  ...         """Subclasses must implement this as a @staticmethod"""
  ...          pass

อัปเดต - อีกวิธีในการอธิบาย:

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


4

ขณะนี้ไม่สามารถทำได้ใน Python 2.X ซึ่งจะบังคับให้เมธอดเป็นนามธรรมหรือคงที่เท่านั้น แต่ไม่ใช่ทั้งสองอย่าง

ใน Python 3.2+ ผู้ตกแต่งใหม่abc.abstractclassmethodและabc.abstractstaticmethodถูกเพิ่มเข้ามาเพื่อรวมการบังคับใช้เป็นนามธรรมและคงที่หรือนามธรรมและวิธีการคลาส

ดูPython ฉบับที่ 5867


12
ขณะใหม่ใน Python 3.2 abstractclassmethodและabstractstaticmethodเลิกใช้งานอย่างรวดเร็วใน Python 3.3 เช่นเดียวกับabstractproperty. docs.python.org/3/library/abc.html
กลาเรน

4
FYI: bugs.python.org/issue11610 อธิบายถึงการกีดกันและวิธีการใหม่ในการดำเนินการ ...
FlipMcF
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.