什么是甲状腺?它们用于什么?
当前回答
甲特克拉斯(甲特克拉斯)是一类,讲述了(某些)其他类应该是如何形成的。
这是一个案例,我看到甲状腺作为解决我的问题:我有一个真正复杂的问题,可能可以是不同的解决,但我选择用甲状腺解决它。 由于复杂性,这是我写的几个模块之一,在模块上的评论超过了编写的代码的数量。
#!/usr/bin/env python
# Copyright (C) 2013-2014 Craig Phillips. All rights reserved.
# This requires some explaining. The point of this metaclass excercise is to
# create a static abstract class that is in one way or another, dormant until
# queried. I experimented with creating a singlton on import, but that did
# not quite behave how I wanted it to. See now here, we are creating a class
# called GsyncOptions, that on import, will do nothing except state that its
# class creator is GsyncOptionsType. This means, docopt doesn't parse any
# of the help document, nor does it start processing command line options.
# So importing this module becomes really efficient. The complicated bit
# comes from requiring the GsyncOptions class to be static. By that, I mean
# any property on it, may or may not exist, since they are not statically
# defined; so I can't simply just define the class with a whole bunch of
# properties that are @property @staticmethods.
#
# So here's how it works:
#
# Executing 'from libgsync.options import GsyncOptions' does nothing more
# than load up this module, define the Type and the Class and import them
# into the callers namespace. Simple.
#
# Invoking 'GsyncOptions.debug' for the first time, or any other property
# causes the __metaclass__ __getattr__ method to be called, since the class
# is not instantiated as a class instance yet. The __getattr__ method on
# the type then initialises the class (GsyncOptions) via the __initialiseClass
# method. This is the first and only time the class will actually have its
# dictionary statically populated. The docopt module is invoked to parse the
# usage document and generate command line options from it. These are then
# paired with their defaults and what's in sys.argv. After all that, we
# setup some dynamic properties that could not be defined by their name in
# the usage, before everything is then transplanted onto the actual class
# object (or static class GsyncOptions).
#
# Another piece of magic, is to allow command line options to be set in
# in their native form and be translated into argparse style properties.
#
# Finally, the GsyncListOptions class is actually where the options are
# stored. This only acts as a mechanism for storing options as lists, to
# allow aggregation of duplicate options or options that can be specified
# multiple times. The __getattr__ call hides this by default, returning the
# last item in a property's list. However, if the entire list is required,
# calling the 'list()' method on the GsyncOptions class, returns a reference
# to the GsyncListOptions class, which contains all of the same properties
# but as lists and without the duplication of having them as both lists and
# static singlton values.
#
# So this actually means that GsyncOptions is actually a static proxy class...
#
# ...And all this is neatly hidden within a closure for safe keeping.
def GetGsyncOptionsType():
class GsyncListOptions(object):
__initialised = False
class GsyncOptionsType(type):
def __initialiseClass(cls):
if GsyncListOptions._GsyncListOptions__initialised: return
from docopt import docopt
from libgsync.options import doc
from libgsync import __version__
options = docopt(
doc.__doc__ % __version__,
version = __version__,
options_first = True
)
paths = options.pop('<path>', None)
setattr(cls, "destination_path", paths.pop() if paths else None)
setattr(cls, "source_paths", paths)
setattr(cls, "options", options)
for k, v in options.iteritems():
setattr(cls, k, v)
GsyncListOptions._GsyncListOptions__initialised = True
def list(cls):
return GsyncListOptions
def __getattr__(cls, name):
cls.__initialiseClass()
return getattr(GsyncListOptions, name)[-1]
def __setattr__(cls, name, value):
# Substitut option names: --an-option-name for an_option_name
import re
name = re.sub(r'^__', "", re.sub(r'-', "_", name))
listvalue = []
# Ensure value is converted to a list type for GsyncListOptions
if isinstance(value, list):
if value:
listvalue = [] + value
else:
listvalue = [ None ]
else:
listvalue = [ value ]
type.__setattr__(GsyncListOptions, name, listvalue)
# Cleanup this module to prevent tinkering.
import sys
module = sys.modules[__name__]
del module.__dict__['GetGsyncOptionsType']
return GsyncOptionsType
# Our singlton abstract proxy class.
class GsyncOptions(object):
__metaclass__ = GetGsyncOptionsType()
其他回答
看这:
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中,一类是指一个子类的子类,它决定一个子类的行为方式;在Python中,一类是另一个子类的例子;在Python中,一类是指一个子类的例子将如何行事。
由于甲基层负责类型,所以你可以写自己的自定义甲基层来改变类型是通过执行额外的操作或注射代码创建的方式。
请注意,在Python 3.6中,引入了一个新的Dunder方法 __init_subclass__(cls, **kwargs),以取代许多常见的使用案例为MetaClass。
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类中,也需要第一类对象才能实现这种行为。
我从来没有自己写过一个,但我认为在Django框架中可以看到最可爱的用途之一。模型类使用一个模型类的方法,以允许写新的模型或形式类的宣言风格。
剩下的就是:如果你不知道什么是金属玻璃,那么你不需要它们的可能性是99%。
推荐文章
- 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中重置生成器对象