Tak, to jest przydatne i ma służyć cel, ale jest również dość rzadkie, aby to zrobić. Jeśli uważasz, że musisz poprawiać klasy po ich zdefiniowaniu, zawsze powinieneś przestać i zastanowić się, czy to naprawdę najlepszy sposób.
Jedną z sytuacji jest łatanie małp.Zrobiłem to w dużym systemie Plone, gdzie niektóre metody wymagały drobnych poprawek, ale nie było prostego sposobu na normalne obejście tego zachowania. W tej sytuacji, w której masz złożoną bibliotekę, możesz łatwo wprowadzić nowe lub zmodyfikowane zachowanie bez konieczności zmiany oryginalnej biblioteki.
Inną sytuacją, która przychodzi na myśl, jest to, że potrzebujesz wielu metod, które mogą być generowane automatycznie. na przykład testy oparte na danych.
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)
gdy MyTestCase jest unittest.TestCase można mieć jeden test, który przechodzi przez wszystkie dane, ale zatrzymuje się na pierwszym niepowodzeniu, a ty nie masz, aby spróbować dowiedzieć się, które zawiodły linia danych. Poprzez dynamiczne tworzenie metod wszystkie testy są uruchamiane osobno, a nazwa testu mówi, która z nich się nie powiodła (oryginał powyższego kodu rzeczywiście zbudował bardziej znaczącą nazwę, zawierającą niektóre dane, a także indeks).
Nie można tego zrobić wewnątrz ciała klasy, ponieważ nie ma możliwości odwołania się do samej klasy lub jej słownika przed ukończeniem definicji. Możesz jednak zrobić coś podobnego za pomocą metaklasy, która pozwala modyfikować dyktando klasy przed stworzeniem samej klasy, a czasami jest to czystszy sposób robienia tego samego.
Inną rzeczą, na którą należy zwrócić uwagę, są sytuacje, w których to nie zadziała. Niektóre metody specjalne __xxx__
nie mogą zostać nadpisane po utworzeniu klasy: oryginalna definicja jest zapisywana wewnętrznie w innym miejscu niż klasa __dict__
, więc wszelkie zmiany wprowadzone później mogą zostać zignorowane. Również w przypadku pracy z metaclasses czasami dodatkowe funkcje nie otrzymają żadnego traktowania, które metaclass nadaje atrybutom jako części definicji klasy.
Interesujące! Wskazuje to również, że inną wartością może być przeniesienie definicji metod, które nie są kluczowe dla klasy w innym miejscu. Oczywiście w szczególnych sytuacjach. –