Do czego przydatne są metaklasy Pythona?

Co można zrobić z metaklasami, które nie mogą być w żaden inny sposób?

Alex Martelli powiedział, że istnieją zadania, których nie można osiągnąć bez metaklasy metaklasy Pythona vs dekoratory klas Chciałbym wiedzieć, które są?

Author: Community, 2010-01-05

8 answers

Metaklasy są niezbędne, jeśli chcesz mieć obiekty klasy (w przeciwieństwie do instancje obiektów klasy) wyposażone w "specjalne niestandardowe zachowanie", ponieważ zachowanie obiektu zależy od specjalnych metod od typu obiektu, a typ obiektu klasy jest dokładnie synonimem metaklasy.

Na przykład, jeśli chcesz obiekt klasy X taki, że "print X" emituje " Time is now 8: 46 AM "(at 8:46 am, or, ogólniej, the current time) to musi oznacza to, że type(x) (aka metaclass X) ma specjalną metodę __str__ -- i podobnie (z różnymi stosowanymi metodami specjalnymi), jeśli chcesz nadać znaczenie wyrażeniom takim jak X + Y gdzie X i Y są obiema obiektami klasowymi, lub X[23] (gdzie x, ponownie, jest obiektem klasowym), i tak dalej.

Większość innych zadań dostosowywania jest teraz (w Pythonie 2.6 lub lepszym) łatwiejsza do zaimplementowania za pomocą dekoratora klasy, który może zmieniać obiekt klasy zaraz po zakończeniu instrukcji class. Istnieją kilka innych przypadków, w których nie jest to możliwe, ponieważ zmiany muszą być wprowadzone bardzo wcześnie, jeśli mają mieć jakikolwiek skutek (np. ustawienie lub zmiana __slots__).

W Pythonie 3 metaklasy zyskują jedną dodatkową użyteczność: metaklasa może teraz opcjonalnie określić obiekt mapowania, który ma być wypełniony podczas wykonywania ciała instrukcji class (domyślnie jest to normalne dict). Pozwala to zachować i używać porządku wiązań nazw w ciele klasy (podczas gdy normal dict traci porządek), co jest czasem miłe, gdy klasa musi mieć "pola" w określonej kolejności (np. aby odwzorować 1:1 Na C struct, wiersz w pliku CSV lub tabeli DB i tym podobne) -- w Pythonie 2.* to musiało być redundantnie określone (zazwyczaj z dodatkowym atrybutem klasy, który jest sekwencją, a tym samym zachowuje porządek), a ta cecha Metaklasów Pythona 3 pozwala na usunięcie redundancji.

 18
Author: Alex Martelli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-05 16:58:28

Dodaj dodatkową elastyczność do programowania:

Ale zgodnie z tym Metaclass programowania w Pythonie możesz ich nie potrzebować (jeszcze)

Metaklasy są głębszą magią niż 99% użytkowników powinno się martwić. Jeśli zastanawiasz się, czy ich potrzebujesz ,to nie (ludzie, którzy naprawdę ich potrzebują, wiedzą z pewnością, że ich potrzebują i nie potrzebują wyjaśnienia dlaczego).

-- Python Guru Tim Peters

 10
Author: OscarRyz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-05 12:15:51

Używam metaklasy z pewną częstotliwością, i są niezwykle potężnym narzędziem, które można mieć w skrzynce narzędziowej. Czasami rozwiązanie problemu może być bardziej eleganckie, mniej kodu, z nimi niż bez.

Rzecz, do której najczęściej używam metaklasy, to przetwarzanie atrybutów klasy podczas tworzenia klasy. Na przykład ustawienie atrybutu name na obiektach, gdzie jest to właściwe (jak może działać ORM Django):

class AutonamingType(type):
    def __init__(cls, name, bases, attrs):
        for k,v in attrs.iteritems():
            if getattr(v, '__autoname__', False):
                v.name = k

class Autonamer(object):
    __metaclass__ = AutonamingType

Jeśli masz to jako narzędzie i jesteś używając klasy, która musi znać swoją name zanim będzie mogła do_something():

class Foo(object):
    __autoname__ = True
    def __init__(self, name=None):
        self.name = name
    def do_something(self):
        if self.name is None:
            raise ValueError('name is None')
        # now, do something

Może to zrobić różnicę w pozostałej części kodu między tym:

class Bar(object):
    myfoo1 = Foo('myfoo1')
    myfoo2 = Foo('myfoo2')
    myfoo3 = Foo('myfoo3')

I to:

class Baaz(Autonamer):
    myfoo1 = Foo()
    myfoo2 = Foo()
    myfoo3 = Foo()

W ten sposób zmniejszając duplikację (i szanse, że nazwa zmiennej i przypisana Nazwa mogą się nie zsynchronizować).

 8
Author: Matt Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-05 15:13:05

Jeśli szukasz przykładów użycia mechanizmu metaclass, możesz przeczytać kod źródłowy django.formularze .

Deklaratywny styl definicji formy jest zaimplementowany za pomocą metaclass.

 4
Author: satoru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-05 12:19:01

Są one rzadko potrzebne, ale są przydatne w miejscach, w których chcesz dodać zachowanie do podstawowego zachowania obiektu - porównaj Programowanie Aspect Oriented lub oprzyrządowanie wykonywane w ramach persistence, takich jak Hibernate.

Na przykład, możesz chcieć mieć klasę, która utrzymuje lub rejestruje każdy nowy obiekt.

 1
Author: Joshua Fox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-05 12:18:29

Prawdopodobnie nie ma nic, co można zrobić wyłącznie z metaklasami, ale dla niektórych osób (w tym Moich) jest to ciekawe narzędzie, z którego można korzystać. Po prostu uważaj, aby nie nadużywać, ponieważ może to być trudne.

Na przykład, używałem metaprogramowania w niedawnym projekcie. Był to arkusz calc OpenOffice, który za pomocą niektórych makr pyUNO generuje niektóre pliki z informacjami. Był jeden arkusz, który przedstawia użytkownikowi informacje do wypełnienia, a inne mogą być używane do opisania rodzaju elementy i ich właściwości. Użytkownik może następnie wybrać liczbę elementów i typ każdego z nich i wygenerować pliki. Makro utworzy klasę poprzez metaprogramowanie zgodnie z konfiguracją na każdym arkuszu. Następnie użytkownik może instancjować każdą klasę i generować obiekty.

MoĹźna to zrobiÄ ‡ bez metaprogramowania, ale dla mnie naturalne byĹ 'o wykorzystanie do tego moĹźliwoĹ" ci metaprogramowania.

 1
Author: Khelben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-05 12:26:01

Spójrz na źródła Django - na przykład metaklasy są tam używane do generowania modeli.

Http://code.djangoproject.com/wiki/DynamicModels

Wewnętrznie, Django używa metaklasy do tworzenie modeli w oparciu o klasę ty podaj swój kod źródłowy. Bez wchodzenie w zbyt wiele szczegółów, że oznacza, że zamiast klas będąc prawdziwymi modelami, Django otrzymuje opis swojej klasy, które wykorzystuje do stworzenia modelu w swoim miejsce.

 1
Author: bluszcz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-05 13:21:58

Pierwszy komentator stwierdza, że użycie metaklasy tutaj było 'kamieniem szlachetnym', który pomógł mu wytropić nieoczekiwane błędy, które występowały przez (wiele)'dni'.

 0
Author: mistermarko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-25 07:59:16