什么是甲状腺?它们用于什么?


当前回答

Metaclasses 是做“类”的工作的秘密酱油,新风格对象的默认 metaclass 被称为“类型”。

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

Metaclasses 取 3 args. 'name', 'bases' 和 '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

请注意,启动者获得的魔法行为是通过拥有金属类的 init_属性而没有转移到启动者的子类。

这里是一个更具体的例子,显示如何可以创建一个在创建一个类时执行一个行动的甲型类的“类型”。

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

其他回答

型()函数可以返回对象的类型或创建一个新的类型,

例如,我们可以使用类()函数创建一个 Hi 类,并且不需要使用类 Hi(对象):

def func(self, name='mike'):
    print('Hi, %s.' % name)

Hi = type('Hi', (object,), dict(hi=func))
h = Hi()
h.hi()
Hi, mike.

type(Hi)
type

type(h)
__main__.Hi

除了使用类()以动态创建类,您还可以控制类的创建行为,并使用甲塔克拉斯。

根据 Python 对象模型,类是对象,所以类必须是另一个特定的类的例子. 默认情况下, Python 类是类类类的例子. 也就是说,类是大多数内置类的甲型类和用户定义类的甲型类。

class ListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)
        return type.__new__(cls, name, bases, attrs)

class CustomList(list, metaclass=ListMetaclass):
    pass

lst = CustomList()
lst.add('custom_list_1')
lst.add('custom_list_2')

lst
['custom_list_1', 'custom_list_2']

魔法将有效,当我们通过关键词论点在Metaclass,它指示Python翻译器通过ListMetaclass创建CustomList。新(),在此时,我们可以修改类定义,例如,并添加一个新的方法,然后返回修订的定义。

什么是Metaclasses?你用它们用于什么?

>>> Class(...)
instance

>>> Metaclass(...)
Class

>>> type('Foo', (object,), {}) # requires a name, bases, and a namespace
<class '__main__.Foo'>

每当你创建一个类时,你都会使用一个类型:

class Foo(object): 
    'demo'

>>> Foo
<class '__main__.Foo'>
>>> isinstance(Foo, type), isinstance(Foo, object)
(True, True)

name = 'Foo'
bases = (object,)
namespace = {'__doc__': 'demo'}
Foo = type(name, bases, namespace)

>>> Foo.__dict__
dict_proxy({'__dict__': <attribute '__dict__' of 'Foo' objects>, 
'__module__': '__main__', '__weakref__': <attribute '__weakref__' 
of 'Foo' objects>, '__doc__': 'demo'})

(在 __dict__: __module__ 类的内容上有一个侧笔记,因为类必须知道它们在哪里定义,而 __dict__ 和 __weakref__ 是因为我们不定义 __slots__ - 如果我们定义 __slots__ 我们会在例子中节省一些空间,因为我们可以通过排除它们来排除 __dict__ 和 __weakref__。

>>> Baz = type('Bar', (object,), {'__doc__': 'demo', '__slots__': ()})
>>> Baz.__dict__
mappingproxy({'__doc__': 'demo', '__slots__': (), '__module__': '__main__'})

我们可以像任何其他类定义一样扩展类型:

>>> Foo
<class '__main__.Foo'>

class Type(type):
    def __repr__(cls):
        """
        >>> Baz
        Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None})
        >>> eval(repr(Baz))
        Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None})
        """
        metaname = type(cls).__name__
        name = cls.__name__
        parents = ', '.join(b.__name__ for b in cls.__bases__)
        if parents:
            parents += ','
        namespace = ', '.join(': '.join(
          (repr(k), repr(v) if not isinstance(v, type) else v.__name__))
               for k, v in cls.__dict__.items())
        return '{0}(\'{1}\', ({2}), {{{3}}})'.format(metaname, name, parents, namespace)
    def __eq__(cls, other):
        """
        >>> Baz == eval(repr(Baz))
        True            
        """
        return (cls.__name__, cls.__bases__, cls.__dict__) == (
                other.__name__, other.__bases__, other.__dict__)

>>> class Bar(object): pass
>>> Baz = Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None})
>>> Baz
Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None})

但是,与 eval(repr(Class))的进一步检查是不可能的(因为函数将是相当不可能从他们的默认 __repr__ 的 eval 。

from collections import OrderedDict

class OrderedType(Type):
    @classmethod
    def __prepare__(metacls, name, bases, **kwargs):
        return OrderedDict()
    def __new__(cls, name, bases, namespace, **kwargs):
        result = Type.__new__(cls, name, bases, dict(namespace))
        result.members = tuple(namespace)
        return result

class OrderedMethodsObject(object, metaclass=OrderedType):
    def method1(self): pass
    def method2(self): pass
    def method3(self): pass
    def method4(self): pass

>>> OrderedMethodsObject.members
('__module__', '__qualname__', 'method1', 'method2', 'method3', 'method4')

>>> inspect.getmro(OrderedType)
(<class '__main__.OrderedType'>, <class '__main__.Type'>, <class 'type'>, <class 'object'>)

而且它大约有正确的回报(除非我们能找到代表我们的功能的方式,否则我们就不能再评估):

>>> OrderedMethodsObject
OrderedType('OrderedMethodsObject', (object,), {'method1': <function OrderedMethodsObject.method1 at 0x0000000002DB01E0>, 'members': ('__module__', '__qualname__', 'method1', 'method2', 'method3', 'method4'), 'method3': <function OrderedMet
hodsObject.method3 at 0x0000000002DB02F0>, 'method2': <function OrderedMethodsObject.method2 at 0x0000000002DB0268>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'OrderedMethodsObject' objects>, '__doc__': None, '__d
ict__': <attribute '__dict__' of 'OrderedMethodsObject' objects>, 'method4': <function OrderedMethodsObject.method4 at 0x0000000002DB0378>})

类型实际上是一类 - 创建另一个类的类型. 大多数类型是类型的子类型. 类型接收新类作为其第一个论点,并提供到类对象的访问,如下所述的细节:

>>> class MetaClass(type):
...     def __init__(cls, name, bases, attrs):
...         print ('class name: %s' %name )
...         print ('Defining class %s' %cls)
...         print('Bases %s: ' %bases)
...         print('Attributes')
...         for (name, value) in attrs.items():
...             print ('%s :%r' %(name, value))
... 

>>> class NewClass(object, metaclass=MetaClass):
...    get_choch='dairy'
... 
class name: NewClass
Bases <class 'object'>: 
Defining class <class 'NewClass'>
get_choch :'dairy'
__module__ :'builtins'
__qualname__ :'NewClass'

注:

请注意,课堂在任何时候都没有被暂停;创建课堂的简单行为引发了金属课堂的执行。

在以对象为导向的编程中,一个代码类是一种类,其例子是类。 正如普通类定义某些对象的行为一样,一个代码类定义某些类的行为和其例子 这个术语的代码类简单地意味着用于创建类的东西。

简而言之:一类是创建一个例子的图标,一类是创建一个类的图标,可以很容易地看到,在Python类中,也需要第一类对象才能实现这种行为。

我从来没有自己写过一个,但我认为在Django框架中可以看到最可爱的用途之一。模型类使用一个模型类的方法,以允许写新的模型或形式类的宣言风格。

剩下的就是:如果你不知道什么是金属玻璃,那么你不需要它们的可能性是99%。