什么是甲状腺?它们用于什么?
当前回答
一个用途是自动将新属性和方法添加到一个例子。
例如,如果你看 Django 模型,它们的定义看起来有点困惑。
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
然而,在工作时间里,人体对象充满了各种有用的方法。
其他回答
上面的答案是正确的。
但读者可能来到这里寻找关于类似名称的内部课程的答案,他们在受欢迎的图书馆,如Django和WTForms。
相反,这些是班级的命令之内的名称空间,它们是用内部班级为可读性而建造的。
在这个特殊的例子领域,抽象是显而易见地与作者模型的领域分开。
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
class Meta:
abstract = True
另一个例子是WTForms的文档:
from wtforms.form import Form
from wtforms.csrf.session import SessionCSRF
from wtforms.fields import StringField
class MyBaseForm(Form):
class Meta:
csrf = True
csrf_class = SessionCSRF
name = StringField("name")
这个合成不会在Python编程语言中得到特别的处理. Meta 不是这里的一个关键词,也不会引发 meta 类行为. 相反,第三方图书馆代码在 Django 和 WTForms 等包中,在某些类的构建者和其他地方读到这个属性。
这些声明的存在改变了具有这些声明的类别的行为. 例如,WTForms 阅读 self.Meta.csrf 以确定表格是否需要一个 csrf 字段。
除了发布的答案,我可以说,一个甲状腺可以定义一个类的行为,所以,你可以明确设置你的甲状腺,每当Python获得一个关键词类,然后它开始搜索甲状腺,如果它没有找到 - 默认甲状腺类型用于创建一个类的对象,使用 __metaclass__属性,你可以设置你的甲状腺类:
class MyClass:
__metaclass__ = type
# write here other method
# write here one more method
print(MyClass.__metaclass__)
它将产生这样的产量:
class 'type'
当然,你可以创建自己的金属类来定义使用你的类创建的任何类的行为。
要做到这一点,您的默认金属类型类必须继承,因为这是主要金属类:
class MyMetaClass(type):
__metaclass__ = type
# you can write here any behaviour you want
class MyTestClass:
__metaclass__ = MyMetaClass
Obj = MyTestClass()
print(Obj.__metaclass__)
print(MyMetaClass.__metaclass__)
产量将是:
class '__main__.MyMetaClass'
class 'type'
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
在以对象为导向的编程中,一个代码类是一种类,其例子是类。 正如普通类定义某些对象的行为一样,一个代码类定义某些类的行为和其例子 这个术语的代码类简单地意味着用于创建类的东西。
下面是另一个例子,它可以用于什么:
您可以使用甲状腺来改变其例子(类)的功能。
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()
金星是强大的,有很多事情(如猴子魔法)你可以用它,但要小心,这可能只是你知道的。
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录