Да, это полезно и служит определенной цели, но это также довольно редко приходится делать.Если вы считаете, что вам нужно исправлять классы после того, как они были определены, вы всегда должны остановиться и подумать, действительно ли это лучший способ.
Одной из ситуаций является исправление обезьян.Я сделал это в большой системе Plone, где некоторым методам требовались незначительные изменения, но просто не было простого способа переопределить поведение в обычном режиме.В той ситуации, когда у вас есть сложная библиотека, она предоставляет простой способ внедрить новое или измененное поведение без необходимости изменять исходную библиотеку.
Другая ситуация, которая приходит на ум, - это когда вам нужно много методов, которыеможет быть создан автоматически.например, тесты, управляемые данными.
def createTest(testcase, somedata, index):
def test(self):
"Do something with somedata and assert a result"
test_name = "test_%d" % index
setattr(testcase, test_name, test)
for index, somedata in enumerate(somebigtable):
createTest(MyTestCase, somedata, index)
, когда MyTestCase является unittest.TestCase, у вас может быть один тест, который проходит через все данные, но останавливается при первом сбое, и вам нужно попытаться выяснить, какойстрока данных не удалась.При динамическом создании методов все тесты выполняются отдельно, а имя теста говорит вам, какой из них не выполнен (оригинал кода выше фактически создал более значимое имя, включающее некоторые данные, а также индекс).
Вы не можете сделать это внутри тела класса, потому что нет никакого способа ни ссылаться на сам класс, ни на его словарь до завершения определения.Однако вы можете сделать что-то похожее с метаклассом, так как это позволит вам изменить dict класса перед созданием самого класса, а иногда это более чистый способ сделать то же самое.
Еще одна вещь, на которую стоит обратить внимание:Есть ситуации, когда это не сработает.Некоторые __xxx__
специальные методы не могут быть переопределены после создания класса: исходное определение сохраняется внутри где-то, кроме __dict__
класса, поэтому любые изменения, которые вы сделаете позже, могут быть проигнорированы.Также при работе с метаклассами иногда дополнительные функции не получают никакой обработки, которую метакласс дает атрибутам как часть определения класса.