Что такое метаклассы в Python?

Вам не нужно принимать во внимание e в e666.76?

С

(e|0-9)\d*\d.\d{1,2)
5279
задан Veltzer Doron 11 January 2018 в 23:18
поделиться

4 ответа

Метакласс является классом класса. Класс определяет, как экземпляр класса (т.е. объект) ведет себя, в то время как метакласс определяет, как класс ведет себя. Класс является экземпляром метакласса.

, В то время как в Python можно использовать произвольный callables для метаклассов (как [1 116] шоу Jerub), лучший подход должен сделать его самим фактическим классом. type обычный метакласс в Python. type самостоятельно класс, и это - свой собственный тип. Вы не будете в состоянии воссоздать что-то как type просто в Python, но Python обманывает немного. Для создания собственного метакласса в Python, Вы действительно просто хотите разделить на подклассы type.

метакласс А обычно используется в качестве фабрики классов. При создании объекта путем вызова класса Python создает новый класс (когда это выполняет оператор 'класса') путем вызова метакласса. Объединенный с нормальным __init__ и __new__ методы, метаклассы поэтому позволяют Вам делать 'дополнительные вещи' при создании класса, как регистрация нового класса с некоторым реестром или заменять класс чем-то еще полностью.

, Когда class оператор выполняется, Python сначала выполняет тело class оператор как нормальный блок кода. Получающееся пространство имен (dict) содержит атрибуты будущего класса. Метакласс определяется путем рассмотрения базовых классов будущего класса (метаклассы наследованы), в __metaclass__ атрибут будущего класса (если таковые имеются) или __metaclass__ глобальная переменная. Метакласс тогда называют с именем, основаниями и атрибутами класса для инстанцирования его.

Однако метаклассы на самом деле определяют тип класса, не только фабрика для него, таким образом, можно сделать намного больше с ними. Можно, например, определить нормальные методы на метаклассе. Эти методы метакласса похожи на classmethods, в котором их можно назвать на классе без экземпляра, но они также не как classmethods, в котором их нельзя назвать на экземпляре класса. type.__subclasses__() пример метода на type метакласс. Можно также определить нормальные 'волшебные' методы, как [1 113], __iter__ и __getattr__, чтобы реализовать или измениться, как класс ведет себя.

Вот агрегированный пример остатков:

def make_hook(f):
    """Decorator to turn 'foo' method into '__foo__'"""
    f.is_hook = 1
    return f

class MyType(type):
    def __new__(mcls, name, bases, attrs):

        if name.startswith('None'):
            return None

        # Go over attributes and see if they should be renamed.
        newattrs = {}
        for attrname, attrvalue in attrs.iteritems():
            if getattr(attrvalue, 'is_hook', 0):
                newattrs['__%s__' % attrname] = attrvalue
            else:
                newattrs[attrname] = attrvalue

        return super(MyType, mcls).__new__(mcls, name, bases, newattrs)

    def __init__(self, name, bases, attrs):
        super(MyType, self).__init__(name, bases, attrs)

        # classregistry.register(self, self.interfaces)
        print "Would register class %s now." % self

    def __add__(self, other):
        class AutoClass(self, other):
            pass
        return AutoClass
        # Alternatively, to autogenerate the classname as well as the class:
        # return type(self.__name__ + other.__name__, (self, other), {})

    def unregister(self):
        # classregistry.unregister(self)
        print "Would unregister class %s now." % self

class MyObject:
    __metaclass__ = MyType


class NoneSample(MyObject):
    pass

# Will print "NoneType None"
print type(NoneSample), repr(NoneSample)

class Example(MyObject):
    def __init__(self, value):
        self.value = value
    @make_hook
    def add(self, other):
        return self.__class__(self.value + other.value)

# Will unregister the class
Example.unregister()

inst = Example(10)
# Will fail with an AttributeError
#inst.unregister()

print inst + inst
class Sibling(MyObject):
    pass

ExampleSibling = Example + Sibling
# ExampleSibling is now a subclass of both Example and Sibling (with no
# content of its own) although it will believe it's called 'AutoClass'
print ExampleSibling
print ExampleSibling.__mro__
2572
ответ дан Cameron Savage 11 January 2018 в 23:18
поделиться
  • 1
    Статические списки инициализатора не применимы в моем случае, как длина только будет известна во времени выполнения. Однако идея использовать версию пары итератора vector конструктор работает хорошо на меня, с тех пор который делает автоматическое преобразование. Обновленный мой вопрос с примером кода. Одна проблема состоит в том, что у меня должно быть отдельное vector для аргументов конструктора, которые останутся в объеме после I' m сделанное использование его, таким образом, I' ll, вероятно, создают некоторую функцию aroud то, что возвращает законченный вектор. Или пользовательские итераторы последовательности. Если только C++ 11 имел ranges†¦ – MvG 15 February 2013 в 14:21

Я думаю, что введение ONLamp в программирование метакласса правильно написано и уже дает действительно хорошее введение в тему несмотря на то, чтобы быть несколькими годами.

http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html (заархивированный в https://web.archive.org/web/20080206005253/http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html )

Короче говоря: класс является проектом создания экземпляра, метакласс является проектом создания класса. Можно легко заметить, что в классах Python должны быть первоклассные объекты также для включения этого поведения.

я никогда не писал тот сам, но я думаю, что одно из самого хорошего использования метаклассов видно в платформа Django . Образцовые классы используют подход метакласса для включения декларативного стиля записи новых моделей или классов формы. В то время как метакласс создает класс, все участники получают возможность настроить сам класс.

вещь, это оставляют сказать: Если Вы не знаете, каковы метаклассы, вероятность, что Вам не будут нужны они , составляет 99%.

108
ответ дан Yet Another User 11 January 2018 в 23:18
поделиться

Примечание, этот ответ для Python 2.x, как это было записано в 2008, метаклассы немного отличаются в 3.x.

Метаклассы являются секретным соусом, которые заставляют 'класс' работать. Метакласс по умолчанию для модернизированного объекта называют 'типом'.

class type(object)
  |  type(object) -> the object's type
  |  type(name, bases, dict) -> a new type

Метаклассы берут 3 args'. имя ', ' основания ' и' dict'

Вот - то, где секрет запускается. Ищите, куда имя, основания и dict прибывают из в этом определении класса в качестве примера.

class ThisIsTheName(Bases, Are, Here):
    All_the_code_here
    def doesIs(create, a):
        dict

Позволяет, определяют метакласс, который продемонстрирует как' класс: ' вызовы это.

def test_metaclass(name, bases, dict):
    print 'The Class Name is', name
    print 'The Class Bases are', bases
    print 'The dict has', len(dict), 'elems, the keys are', dict.keys()

    return "yellow"

class TestName(object, None, int, 1):
    __metaclass__ = test_metaclass
    foo = 1
    def baz(self, arr):
        pass

print 'TestName = ', repr(TestName)

# output => 
The Class Name is TestName
The Class Bases are (<type 'object'>, None, <type 'int'>, 1)
The dict has 4 elems, the keys are ['baz', '__module__', 'foo', '__metaclass__']
TestName =  'yellow'

И теперь, пример, который на самом деле означает что-то, это автоматически сделает переменные в наборе "атрибутов" списка на классе и не установит ни на Один.

def init_attributes(name, bases, dict):
    if 'attributes' in dict:
        for attr in dict['attributes']:
            dict[attr] = None

    return type(name, bases, dict)

class Initialised(object):
    __metaclass__ = init_attributes
    attributes = ['foo', 'bar', 'baz']

print 'foo =>', Initialised.foo
# output=>
foo => None

Примечание, что волшебное поведение, что усиления 'Initalised' при наличии метакласса init_attributes не передаются на подкласс Initalised.

Вот еще более конкретный пример, показывая, как можно разделить 'тип' на подклассы для создания метакласса, который выполняет действие, когда класс создается. Это довольно хитро:

class MetaSingleton(type):
    instance = None
    def __call__(cls, *args, **kw):
        if cls.instance is None:
            cls.instance = super(MetaSingleton, cls).__call__(*args, **kw)
        return cls.instance

class Foo(object):
    __metaclass__ = MetaSingleton

a = Foo()
b = Foo()
assert a is b
370
ответ дан Ajithkumar_sekar 11 January 2018 в 23:18
поделиться
  • 1
    После пребывания в течение некоторого времени, анализируя и играя вокруг с ним, я смог получить некоторые результаты, утонченные с классом QRCodeReader и передающий в моем собственном Битовом массиве, но я должен был сделать ручные преобразования с другими классами, такими как классы Binarizer и BinaryBitmap. Это doesn' t походят на так большую часть библиотеки, чем выбор классов. – Jay Snayder 27 December 2013 в 17:29

Одно использование для метаклассов добавляет новые свойства и методы к экземпляру автоматически.

, Например, если Вы смотрите модели Django , их определение выглядит немного сбивающим с толку. Выглядит, как будто Вы только определяете свойства класса:

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

Однако во времени выполнения объекты Человека заполнены всеми видами полезных методов. Посмотрите источник для некоторого удивительного metaclassery.

148
ответ дан Antti Rasinen 11 January 2018 в 23:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: