ผู้ตกแต่งชั้นเรียนใน Python: กรณีใช้งานจริง


9

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

@register
class MyPlugin(Plugin):
    pass

หรือ

@recieves_notifications
class Console:
    def print(self, text):
        ...

กรณีที่มีเหตุผลอื่น ๆ ที่ฉันคิดว่าอาจถูกสร้างขึ้นจากการสืบทอด metaclasses หรือวิธีการตกแต่ง คุณช่วยแบ่งปันตัวอย่างที่ดี (หรือไม่ดี) ของการใช้เครื่องมือตกแต่งชั้นเรียนได้ไหม?

ขอบคุณ!


สำหรับผู้เริ่มต้นนักตกแต่งจะมีแนวคิดที่ง่ายกว่าเมคาคลาส มันง่ายกว่าการเขียนมัณฑนากรมากกว่า metaclass และหลีกเลี่ยงการคิดวิธีรวมหลาย metaclass โดยไม่ทำลายอะไรเลย
amon

@amon เมื่อมีการใช้ metaclass โดยนักพัฒนาที่มีประสบการณ์มักจะหมายถึงตัวเลือกอื่น ๆ ที่ได้รับการพิจารณาอย่างละเอียดและ metaclass นั้นเป็นวิธีที่ดีที่สุดในการแก้ไขปัญหา ยิ่งกว่านั้นชัดเจนดีกว่าโดยนัย - นั่นอาจเป็นเหตุผลว่าทำไมเรา (มีตัวอย่าง) ABCMetaไม่ใช่@abstractclassผู้ตกแต่งชั้นเรียน
Zaur Nasibov

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

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

คำตอบ:


8

เมื่อทำการทดสอบหน่วยการเรียนรู้ที่มี@unittest.skipIfและ@unittest.skipUnlessสามารถนำไปใช้กับวิธีการของแต่ละบุคคลหรือในการunittest.TestCaseกำหนดระดับทั้งหมด สิ่งนี้ทำให้การเขียนการทดสอบสำหรับปัญหาเฉพาะแพลตฟอร์มง่ายขึ้นมาก

ตัวอย่างจาก asyncio/test_selectors

# Some platforms don't define the select.kqueue object for these tests.
# On those platforms, this entire grouping of tests will be skipped.

@unittest.skipUnless(hasattr(selectors, 'KqueueSelector'),
                 "Test needs selectors.KqueueSelector)")
class KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn):
...

2

นักตกแต่งชั้นเรียนถูกสร้างขึ้นอย่างชัดเจนเพื่อทำให้บางสิ่งที่ชัดเจนผ่าน metaclasses ที่น่าพอใจมากขึ้นจาก PEP :

แรงบันดาลใจกรณีใช้งานคือการทำให้การสร้างบางอย่างง่ายขึ้นและเชื่อถือได้น้อยลงในรายละเอียดการใช้งานของ CPython interpreter แม้ว่ามันจะเป็นไปได้ที่จะแสดงฟังก์ชั่นที่คล้ายกับมัณฑนากรระดับโดยใช้ metaclasses แต่ผลลัพธ์ก็ไม่เป็นที่พอใจและการใช้งานมีความเปราะบางสูง นอกจากนี้ metaclasses ได้รับการสืบทอดในขณะที่ decorators ของชั้นเรียนไม่ได้ทำให้ metaclasses ไม่เหมาะสมสำหรับการใช้งานของ decorators ของชั้นเรียนที่เฉพาะเจาะจง ความจริงที่ว่าโครงการ Python ขนาดใหญ่อย่าง Zope ได้ผ่านการถกเถียงกันอย่างดุเดือดเหล่านี้เพื่อให้ได้สิ่งที่ผู้ตกแต่งชั้นเรียนได้รับชัยชนะเหนือ BDFL


ขอบคุณที่อ้างถึง PEP-3129 อย่างไรก็ตามคำถามไม่ได้เกี่ยวกับสาเหตุที่มีนักตกแต่งในชั้นเรียนความคิดของกุยโด้และ Zope หรือ IronPython จะใช้มันได้อย่างไรก่อนที่พวกเขาจะปรากฏตัว คำถามเกี่ยวกับการใช้งานจริงของพวกเขาในวันนี้ในปี 2559
Zaur Nasibov

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

คุณกำลังทิ้งคำถามเพิ่มเติมที่ตอบ "... จุดทั้งหมดของนักตกแต่งคือการใช้งานง่ายกว่าและชัดเจนกว่า metaclasses" - ในกรณีใดบ้าง ถ้าอย่างนั้น "... คุณควรใช้มัณฑนากรเพราะคนอื่นเข้าใจง่ายกว่า" จริงเหรอ? เป็นเวลานานในการติดยาเสพติดกับงูหลามฉันเคยเห็น metaclasses มากมายน่าเกลียดบ้างสวยงาม แต่ยังไม่ได้ค้นพบนักตกแต่งชั้นเรียนเลย
Zaur Nasibov

1

จากคำถามล้นสแต็คนี้ :

def singleton(class_):
  instances = {}
  def getinstance(*args, **kwargs):
    if class_ not in instances:
        instances[class_] = class_(*args, **kwargs)
    return instances[class_]
  return getinstance

@singleton
class MyClass(BaseClass):
  pass

ใช่ แต่การต้านถูกให้ในคำถาม SO เดียวกัน: metaclass เป็นวิธีที่ดีกว่า
Zaur Nasibov

1

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

Python 2:

def register(target):
    print 'Registring', target
    return target


class ApplyDecorator(type):
    def __new__(mcs, name, bases, attrs):
        decorator = attrs.pop('_decorator')
        cls = type(name, bases, attrs)
        return decorator(cls)

    def __init__(cls, name, bases, attrs, decorator=None):
        super().__init__(name, bases, attrs)


class Foo:
    __metaclass__ = ApplyDecorator
    _decorator = register

Python 3:

def register(target):
    print('Registring', target)
    return target


class ApplyDecorator(type):
    def __new__(mcs, name, bases, attrs, decorator):
        cls = type(name, bases, attrs)
        return decorator(cls)

    def __init__(cls, name, bases, attrs):
        super().__init__(name, bases, attrs)


class Foo(metaclass=ApplyDecorator, decorator=register):
    pass

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