什么是甲状腺?它们用于什么?
当前回答
一个用途是自动将新属性和方法添加到一个例子。
例如,如果你看 Django 模型,它们的定义看起来有点困惑。
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
然而,在工作时间里,人体对象充满了各种有用的方法。
其他回答
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
看这:
Python 3.10.0rc2 (tags/v3.10.0rc2:839d789, Sep 7 2021, 18:51:45) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> class Object:
... pass
...
>>> class Meta(type):
... test = 'Worked!!!'
... def __repr__(self):
... return 'This is "Meta" metaclass'
...
>>> class ObjectWithMetaClass(metaclass=Meta):
... pass
...
>>> Object or type(Object())
<class '__main__.Object'>
>>> ObjectWithMetaClass or type(ObjectWithMetaClass())
This is "Meta" metaclass
>>> Object.test
AttributeError: ...
>>> ObjectWithMetaClass.test
'Worked!!!'
>>> type(Object)
<class 'type'>
>>> type(ObjectWithMetaClass)
<class '__main__.Meta'>
>>> type(type(ObjectWithMetaClass))
<class 'type'>
>>> Object.__bases__
(<class 'object'>,)
>>> ObjectWithMetaClass.__bases__
(<class 'object'>,)
>>> type(ObjectWithMetaClass).__bases__
(<class 'type'>,)
>>> Object.__mro__
(<class '__main__.Object'>, <class 'object'>)
>>> ObjectWithMetaClass.__mro__
(This is "Meta" metaclass, <class 'object'>)
>>>
换句话说,当一个对象没有创建(对象类型),我们正在寻找MetaClass。
简而言之:一类是创建一个例子的图标,一类是创建一个类的图标,可以很容易地看到,在Python类中,也需要第一类对象才能实现这种行为。
我从来没有自己写过一个,但我认为在Django框架中可以看到最可爱的用途之一。模型类使用一个模型类的方法,以允许写新的模型或形式类的宣言风格。
剩下的就是:如果你不知道什么是金属玻璃,那么你不需要它们的可能性是99%。
Python 3 更新
在一个甲状腺中,有(目前)两个关键方法:
__prepare__ 允许您提供自定义地图(如 OrderedDict)作为名称空间使用,而类正在创建。
__new__ 负责最终类的实际创建/修改。
一个色彩色彩,不做任何东西 - 额外的金属类会喜欢:
class Meta(type):
def __prepare__(metaclass, cls, bases):
return dict()
def __new__(metacls, cls, bases, clsdict):
return super().__new__(metacls, cls, bases, clsdict)
一个简单的例子:
说你想要一些简单的验证代码在你的属性上运行 - 因为它必须总是一个 int 或 str. 没有一个 metaclass,你的类会看起来像:
class Person:
weight = ValidateType('weight', int)
age = ValidateType('age', int)
name = ValidateType('name', str)
正如你可以看到的那样,你必须重复属性的名称两次,这使得类型与刺激的错误一起可能。
一个简单的甲状腺可以解决这个问题:
class Person(metaclass=Validator):
weight = ValidateType(int)
age = ValidateType(int)
name = ValidateType(str)
class Validator(type):
def __new__(metacls, cls, bases, clsdict):
# search clsdict looking for ValidateType descriptors
for name, attr in clsdict.items():
if isinstance(attr, ValidateType):
attr.name = name
attr.attr = '_' + name
# create final class and return it
return super().__new__(metacls, cls, bases, clsdict)
一个样本运行:
p = Person()
p.weight = 9
print(p.weight)
p.weight = '9'
生产:
9
Traceback (most recent call last):
File "simple_meta.py", line 36, in <module>
p.weight = '9'
File "simple_meta.py", line 24, in __set__
(self.name, self.type, value))
TypeError: weight must be of type(s) <class 'int'> (got '9')
注意:这个例子是简单的,它也可能已经完成了一个类装饰师,但假设一个真正的金属玻璃会做得更多。
class ValidateType:
def __init__(self, type):
self.name = None # will be set by metaclass
self.attr = None # will be set by metaclass
self.type = type
def __get__(self, inst, cls):
if inst is None:
return self
else:
return inst.__dict__[self.attr]
def __set__(self, inst, value):
if not isinstance(value, self.type):
raise TypeError('%s must be of type(s) %s (got %r)' %
(self.name, self.type, value))
else:
inst.__dict__[self.attr] = value
类,在Python,是一个对象,和任何其他对象一样,它是一个例子“什么”。这个“什么”是所谓的MetaClass。这个MetaClass是一个特殊类型的类,创造了其他类的对象。因此,MetaClass负责创造新的类。
Class Name Tuple 具有由 Class A 继承的基类 词典具有所有类方法和类变量
另一种方式创建一个金属类是“金属类”的关键词,将金属类定义为一个简单的类,在继承类的参数中,通过金属类=金属类_名称。
Metaclass 可以在以下情况下具体使用:
推荐文章
- Numpy Max vs amax vs maximum
- 我应该在.gitignore文件中添加Django迁移文件吗?
- 每n行有熊猫
- 实例属性attribute_name定义在__init__之外
- 如何获取在Python中捕获的异常的名称?
- 第一次出现的值大于现有值的Numpy
- 如何从Python函数中返回两个值?
- 前一个月的Python日期
- Python中方括号括起来的列表和圆括号括起来的列表有什么区别?
- Python日志记录不输出任何东西
- 每n秒运行特定代码
- SQLAlchemy是否有与Django的get_or_create等价的函数?
- 如何将python datetime转换为字符串,具有可读格式的日期?
- 美丽的汤和提取div及其内容的ID
- 在Python中重置生成器对象