Lớp trang trí trong Python: trường hợp sử dụng thực tế


9

Tôi đang tìm kiếm các trường hợp sử dụng thực tế và không tổng hợp của các nhà trang trí lớp Python. Cho đến nay, trường hợp duy nhất có ý nghĩa với tôi là đăng ký một lớp trong hệ thống thuê bao của nhà xuất bản, ví dụ: plugin hoặc sự kiện, đại loại như:

@register
class MyPlugin(Plugin):
    pass

hoặc là

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

Bất kỳ trường hợp lành mạnh nào khác tôi từng nghĩ có thể đã được xây dựng dựa trên sự kế thừa, siêu hình hoặc phương pháp trang trí. Bạn có thể vui lòng chia sẻ bất kỳ ví dụ tốt (hoặc xấu!) Về việc sử dụng trang trí lớp không?

Cảm ơn bạn!


Đối với người mới bắt đầu, trang trí về mặt khái niệm đơn giản hơn nhiều so với metaclass. Viết trang trí đơn giản hơn nhiều so với siêu dữ liệu và tránh có thể phải tìm ra cách kết hợp nhiều siêu dữ liệu mà không làm hỏng bất cứ thứ gì.
amon

@amon khi metaclass được sử dụng bởi một nhà phát triển dày dạn, điều đó thường có nghĩa là các tùy chọn khác đã được xem xét kỹ lưỡng và metaclass cho đến nay là cách tốt nhất để giải quyết vấn đề. Hơn nữa, rõ ràng là tốt hơn ngầm định - đó có thể là lý do tại sao (như một ví dụ) chúng ta có ABCMeta, không phải là @abstractclasstrang trí lớp.
Zaur Nasibov

2
Tôi là một lập trình viên Python và thật lòng tôi không thấy cần họ. Chỉ vì một tính năng ngôn ngữ tồn tại không có nghĩa là bạn phải hoặc thậm chí nên sử dụng nó. Các nhà thiết kế đưa ra tất cả các loại tính năng điên rồ hóa ra là không cần thiết hoặc thậm chí gây tổn hại với nhận thức muộn màng. Trong thực tế, bạn đã đề cập đến hai tính năng khác như vậy trong câu hỏi của bạn :)
vườn

1
Không phải đôi khi tôi không thể sống mà không có, nhưng một điều tôi thấy hữu ích là sử dụng một trình trang trí lớp để ghi nhật ký tất cả các đầu vào và đầu ra của tất cả các phương thức của lớp.
bgusach

Câu trả lời:


8

Khi viết các bài kiểm tra đơn vị có @unittest.skipIf@unittest.skipUnlesscó thể được sử dụng trên cả hai phương thức riêng lẻ hoặc trên toàn bộ unittest.TestCaseđịnh nghĩa lớp. Điều này làm cho việc kiểm tra viết cho các vấn đề cụ thể của nền tảng trở nên dễ dàng hơn nhiều.

Ví dụ từ 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

Các nhà trang trí lớp đã được tạo ra một cách rõ ràng để làm cho một số thứ có thể biểu lộ qua siêu dữ liệu trở nên dễ chịu hơn, từ PEP :

Trường hợp sử dụng có động lực là làm cho các cấu trúc nhất định được thể hiện dễ dàng hơn và ít phụ thuộc hơn vào các chi tiết triển khai của trình thông dịch CPython. Mặc dù có thể biểu thị chức năng giống như trình trang trí lớp bằng cách sử dụng siêu dữ liệu, nhưng kết quả nhìn chung rất khó chịu và việc thực hiện rất mong manh. Ngoài ra, siêu dữ liệu được kế thừa, trong khi các trình trang trí lớp thì không, làm cho các siêu dữ liệu không phù hợp với một số, sử dụng riêng cho từng lớp của các trình trang trí lớp. Thực tế là các dự án Python quy mô lớn như Zope đã trải qua những mâu thuẫn hoang dã này để đạt được thứ gì đó giống như các nhà trang trí lớp đã giành chiến thắng trước BDFL.


Cảm ơn đã trích dẫn PEP-3129. Tuy nhiên, câu hỏi không phải là tại sao các nhà trang trí lớp tồn tại, Guido nghĩ gì về họ và làm thế nào Zope hoặc IronPython có thể sử dụng chúng trước khi chúng xuất hiện. Câu hỏi là về cách sử dụng thực tế của họ ngày hôm nay, trong năm 2016.
Zaur Nasibov

1
Đúng vậy, vấn đề là câu hỏi ban đầu đưa ra siêu dữ liệu như một thứ có thể được sử dụng để thực hiện chức năng giống như trình trang trí lớp, nhưng toàn bộ quan điểm của các nhà trang trí là chúng dễ sử dụng và rõ ràng hơn so với siêu dữ liệu. Vì vậy, câu trả lời cho phần đó của câu hỏi là "Nếu bạn bị giằng xé giữa những người trang trí hoặc siêu hình, bạn nên sử dụng những người trang trí bởi vì những người khác dễ hiểu hơn."
quodlibetor

Bạn đang để lại nhiều câu hỏi mà câu trả lời. "... Toàn bộ quan điểm của các nhà trang trí là chúng dễ sử dụng và rõ ràng hơn so với siêu dữ liệu" - Trong trường hợp nào? Sau đó "... bạn nên sử dụng trang trí bởi vì người khác dễ hiểu hơn" Thật sao? Trong một thời gian dài nghiện Python tôi đã thấy hàng tấn siêu dữ liệu, một số xấu xí, một số đẹp. Nhưng đã không phát hiện ra bất kỳ trang trí lớp học nào cả.
Zaur Nasibov

1

Từ câu hỏi tràn ngăn xếp này :

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

Đúng, nhưng contra được đưa ra ngay trong cùng một câu hỏi SO: metaclass là một cách tiếp cận tốt hơn.
Zaur Nasibov

1

Tìm kiếm các trường hợp sử dụng có thể được thực hiện với các trình trang trí trên các lớp là vô ích - bất cứ điều gì có thể được thực hiện với các trình trang trí trên các lớp đều có thể được thực hiện bằng siêu dữ liệu. Ngay cả ví dụ của bạn về đăng ký. Để chứng minh, đây là một siêu dữ liệu áp dụng một trang trí:

Con trăn 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

Con trăn 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
Như bạn nói - bất cứ điều gì có thể được thực hiện với trang trí. Câu hỏi là, những trường hợp nào nên được thực hiện thông qua trang trí lớp chứ không phải siêu dữ liệu.
Zaur Nasibov
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.