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


当前回答

类,在Python,是一个对象,和任何其他对象一样,它是一个例子“什么”。这个“什么”是所谓的MetaClass。这个MetaClass是一个特殊类型的类,创造了其他类的对象。因此,MetaClass负责创造新的类。

Class Name Tuple 具有由 Class A 继承的基类 词典具有所有类方法和类变量

另一种方式创建一个金属类是“金属类”的关键词,将金属类定义为一个简单的类,在继承类的参数中,通过金属类=金属类_名称。

Metaclass 可以在以下情况下具体使用:

其他回答

其他人已经解释了金属玻璃是如何工作的,它们是如何适应Python类型系统的,这里有一个例子,它们可以用于什么。在我写的测试框架中,我想跟踪在哪个类被定义的顺序,以便我后来能够在这个顺序中安装它们,我发现使用金属玻璃最容易做到这一点。

class MyMeta(type):

    counter = 0

    def __init__(cls, name, bases, dic):
        type.__init__(cls, name, bases, dic)
        cls._order = MyMeta.counter
        MyMeta.counter += 1

class MyType(object):              # Python 2
    __metaclass__ = MyMeta

class MyType(metaclass=MyMeta):    # Python 3
    pass

任何是 MyType 的子类,然后获得一个类属性 _ 命令,记录了类被定义的顺序。

一个用途是自动将新属性和方法添加到一个例子。

例如,如果你看 Django 模型,它们的定义看起来有点困惑。

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

然而,在工作时间里,人体对象充满了各种有用的方法。

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

Python 类本身是它们的 meta 类的对象 - 例如。

默认的金属类,当您确定类时应用于:

class foo:
    ...

例如,假设您正在构建一个ORM访问数据库,并且您希望每个表中的记录来自一个类地图到该表(基于字段,业务规则等),一个可能的使用MetaClass是例如,连接池逻辑,由所有表中的记录的所有类共享。

当你定义甲型时,你可以分类类型,并且可以超越下列魔法方法来插入你的逻辑。

class somemeta(type):
    __new__(mcs, name, bases, clsdict):
      """
  mcs: is the base metaclass, in this case type.
  name: name of the new class, as provided by the user.
  bases: tuple of base classes 
  clsdict: a dictionary containing all methods and attributes defined on class

  you must return a class object by invoking the __new__ constructor on the base metaclass. 
 ie: 
    return type.__call__(mcs, name, bases, clsdict).

  in the following case:

  class foo(baseclass):
        __metaclass__ = somemeta

  an_attr = 12

  def bar(self):
      ...

  @classmethod
  def foo(cls):
      ...

      arguments would be : ( somemeta, "foo", (baseclass, baseofbase,..., object), {"an_attr":12, "bar": <function>, "foo": <bound class method>}

      you can modify any of these values before passing on to type
      """
      return type.__call__(mcs, name, bases, clsdict)


    def __init__(self, name, bases, clsdict):
      """ 
      called after type has been created. unlike in standard classes, __init__ method cannot modify the instance (cls) - and should be used for class validaton.
      """
      pass


    def __prepare__():
        """
        returns a dict or something that can be used as a namespace.
        the type will then attach methods and attributes from class definition to it.

        call order :

        somemeta.__new__ ->  type.__new__ -> type.__init__ -> somemeta.__init__ 
        """
        return dict()

    def mymethod(cls):
        """ works like a classmethod, but for class objects. Also, my method will not be visible to instances of cls.
        """
        pass

无论如何,这两种是最常用的<unk>子,甲板是强大的,上面没有附近和完整的用途列表用于甲板。

下面是另一个例子,它可以用于什么:

您可以使用甲状腺来改变其例子(类)的功能。

class MetaMemberControl(type):
    __slots__ = ()

    @classmethod
    def __prepare__(mcs, f_cls_name, f_cls_parents,  # f_cls means: future class
                    meta_args=None, meta_options=None):  # meta_args and meta_options is not necessarily needed, just so you know.
        f_cls_attr = dict()
        if not "do something or if you want to define your cool stuff of dict...":
            return dict(make_your_special_dict=None)
        else:
            return f_cls_attr

    def __new__(mcs, f_cls_name, f_cls_parents, f_cls_attr,
                meta_args=None, meta_options=None):

        original_getattr = f_cls_attr.get('__getattribute__')
        original_setattr = f_cls_attr.get('__setattr__')

        def init_getattr(self, item):
            if not item.startswith('_'):  # you can set break points at here
                alias_name = '_' + item
                if alias_name in f_cls_attr['__slots__']:
                    item = alias_name
            if original_getattr is not None:
                return original_getattr(self, item)
            else:
                return super(eval(f_cls_name), self).__getattribute__(item)

        def init_setattr(self, key, value):
            if not key.startswith('_') and ('_' + key) in f_cls_attr['__slots__']:
                raise AttributeError(f"you can't modify private members:_{key}")
            if original_setattr is not None:
                original_setattr(self, key, value)
            else:
                super(eval(f_cls_name), self).__setattr__(key, value)

        f_cls_attr['__getattribute__'] = init_getattr
        f_cls_attr['__setattr__'] = init_setattr

        cls = super().__new__(mcs, f_cls_name, f_cls_parents, f_cls_attr)
        return cls


class Human(metaclass=MetaMemberControl):
    __slots__ = ('_age', '_name')

    def __init__(self, name, age):
        self._name = name
        self._age = age

    def __getattribute__(self, item):
        """
        is just for IDE recognize.
        """
        return super().__getattribute__(item)

    """ with MetaMemberControl then you don't have to write as following
    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age
    """


def test_demo():
    human = Human('Carson', 27)
    # human.age = 18  # you can't modify private members:_age  <-- this is defined by yourself.
    # human.k = 18  # 'Human' object has no attribute 'k'  <-- system error.
    age1 = human._age  # It's OK, although the IDE will show some warnings. (Access to a protected member _age of a class)

    age2 = human.age  # It's OK! see below:
    """
    if you do not define `__getattribute__` at the class of Human,
    the IDE will show you: Unresolved attribute reference 'age' for class 'Human'
    but it's ok on running since the MetaMemberControl will help you.
    """


if __name__ == '__main__':
    test_demo()

金星是强大的,有很多事情(如猴子魔法)你可以用它,但要小心,这可能只是你知道的。