- 浏览: 399536 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (309)
- xaml C# wpf (0)
- scala java inner clas (1)
- Tools UML Eclipse UML2 (1)
- Timer .NET Framework (1)
- perl (6)
- python function paramter (1)
- Python Docstring (1)
- Python how to compare types (1)
- Python (8)
- java (5)
- C# (76)
- C# WPF (0)
- p4 (0)
- WPF (46)
- .net (6)
- xaml (1)
- javascript (40)
- windows (10)
- scala (4)
- winform (1)
- c++ (48)
- tools (12)
- cmd (1)
- os (0)
- CI (0)
- shell (0)
- C (2)
- haskell (49)
- functional (1)
- tool (1)
- gnu (1)
- linux (1)
- kaskell (0)
- svn (0)
- wcf (3)
- android (1)
最新评论
the base article is available here: http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python
to understand the metaclass in Python, there is some background that you should be aware in order to grasp the idea of metaclass and its foundation.
Part I:
Classes as object
Given an class declaration:
>>> class ObjectCreator(object): ... pass ... >>> my_object = ObjectCreator() >>> print my_object <__main__.ObjectCreator object at 0x8974f2c>
Classes in Python has more... put it simple. that Classes in Python are objects too.
As soon as keyword class, Python execute it and craete an OBJECT. the instruction
>>> class ObjectCreator(object): ... pass ...
create in memory an object with name ObjectCreator.
what you can do with the Class object.
- you can assign it to a variable
- you can copy it
- you can add attributes to it
- you can pass it as a function parameter
here is an example of how you can do with the class object.
>>> print ObjectCreator # you can print a class because it's an object <class '__main__.ObjectCreator'> >>> def echo(o): ... print o ... >>> echo(ObjectCreator) # you can pass a class as a parameter <class '__main__.ObjectCreator'> >>> print hasattr(ObjectCreator, 'new_attribute') False >>> ObjectCreator.new_attribute = 'foo' # you can add attributes to a class >>> print hasattr(ObjectCreator, 'new_attribute') True >>> print ObjectCreator.new_attribute foo >>> ObjectCreatorMirror = ObjectCreator # you can assign a class to a variable >>> print ObjectCreatorMirror.new_attribute foo >>> print ObjectCreatorMirror() <__main__.ObjectCreator object at 0x8997b4c>
Part II:
Creating Classes Dynamically
In the base article, there is a example demonstrate how to create classes inside a function. But that is not dynamic.
>>> def choose_class(name): ... if name == 'foo': ... class Foo(object): ... pass ... return Foo # return the class, not an instance ... else: ... class Bar(object): ... pass ... return Bar ... >>> MyClass = choose_class('foo') >>> print MyClass # the function returns a class, not an instance <class '__main__.Foo'> >>> print MyClass() # you can create an object from this class <__main__.Foo object at 0x89c6d4c>
Since classes are object, they must be generated by something. the somehting here is the metaclass.
But before we drill down to the Metaclass, let's close exame type keyword .
The following shows what typically you do with type, you get what type an objects is.
>>> print type(1) <type 'int'> >>> print type("1") <type 'str'> >>> print type(ObjectCreator) <type 'type'> >>> print type(ObjectCreator()) <class '__main__.ObjectCreator'>
However, type has more, it has a completely different ability, it can also create classes on the fly...
the function prototyp of type that create types on the fly is as follow.
type(name of the class, tuple of the parent class (for inheritance, can be empty), dictionary containing attributes names and values)
e.g
>>> class MyShinyClass(object): ... pass ... >>> print type(MyShinyClass) <type 'type'> >>> MyShinyClass2 = type('MyShinyClass2', (), {}) >>> print MyShinyClass2 >>> # and then you can create the instance of the dynamically created class ... >>> print MyShinyClass2() <__main__.MyShinyClass2 object at 0x0110CCB0># and then you can cre
So, the following are equivalent.
>>> class Foo(object): ... bar = True
and
>>> Foo = type('Foo', (), {'bar':True})
and after you created Foo (with the type keyword), you uses it as if you have decalred it.
>>> print Foo <class '__main__.Foo'> >>> print Foo.bar True >>> f = Foo() >>> print f <__main__.Foo object at 0x8a9b84c> >>> print f.bar True
Part III:
What are metaclass (finally)
The metaclass, boils down to the following definition:
Metaclasses are the 'stuff' that creates classes, since classes create objects (as well as being objects), so you take that meta classes as class's class
MyClass = MetaClass() MyObject = MyClass()
the following shows step by step by examing the internals of the type system in Python.
A speical note on type method itself.
Checking the __class__ attribute.
>>> age = 35 >>> age.__class__ <type 'int'> >>> name = 'bob' >>> name.__class__ <type 'str'> >>> def foo(): pass >>> foo.__class__ <type 'function'> >>> class Bar(object): pass >>> b = Bar() >>> b.__class__ <class '__main__.Bar'>
But what is the __class__ of the __class__, see following..
>>> a.__class__.__class__ <type 'type'> >>> age.__class__.__class__ <type 'type'> >>> foo.__class__.__class__ <type 'type'> >>> b.__class__.__class__ <type 'type'>
So, they are 'type'.
From the examles above. we can see that a meta class is a "class factory", "type" is the built-in metaclass pythons ues, but of course, you can create your own metaclasses.
Part IV:
the __metaclass__ attribute
the form
class Foo(object): __metaclass__ = something... [...]
remember we said before that Pyton will translate the class declaration to an object, but wait, when there is a __metaclass__ attribute.
Python willl look for __metaclass__ in the class definition. If it finds it, if will use it to create the object classFoo
. If it doesn't, it will use type
to create the class.
The order of searching the __metaclass__ is as follow.
- Is there a __metaclass__ attribute in Foo?
- If yes, create in memory a class object (I said a class object, stay with me here), with the nameFoo by using what is in __metaclass__.
- If Python can't find __metaclass__, it will look for a __metaclass__ in Bar (the parent class), and try to do the same.
- If Python can't find __metaclass__ in any parent, it will look for a __metaclass__ at the MODULE level, and try to do the same.
- Then if it can't find any __metaclass__ at all, it will use type to create the class object.
Part V:
What to put in a custom metaclass
Let's see a stupid example.
Suppose we are creating a metaclasses which will alternate all the attributes of classes that it create to have attributes of the classes to be upper cases.
The following shows how to do that via creating a function as the __metaclass__ (__metaclass__ does not necessary mean it has to be a class) at the module level,
# the metaclass will automatically get passed the same argument # that you usually pass to `type` def upper_attr(future_class_name, future_class_parents, future_class_attr): """ Return a class object, with the list of its attribute turned into uppercase. """ # pick up any attribute that doesn't start with '__' attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__')) # turn them into uppercase uppercase_attr = dict((name.upper(), value) for name, value in attrs) # let `type` do the class creation return type(future_class_name, future_class_parents, uppercase_attr) __metaclass__ = upper_attr # this will affect all classes in the module class Foo(object): # we can define __metaclass__ here instead to affect only this class bar = 'bip' print hasattr(Foo, 'bar') # Out: False print hasattr(Foo, 'BAR') # Out: True f = Foo() print f.BAR # Out: 'bip'
Later, let's do that via the class defintinition
# remember that `type` is actually a class like `str` and `int` # so you can inherit from it class UpperAttrMetaclass(type): # __new__ is the method called before __init__ # it's the method that creates the object and returns it # while __init__ just initializes the object passed as parameter # you rarely use __new__, except when you want to control how the object # is created. # here the created object is the class, and we want to customize it # so we override __new__ # you can do some stuff in __init__ too if you wish # some advanced use involves overriding __call__ as well, but we won't # see this def __new__(upperattr_metaclass, future_class_name, future_class_parents, future_class_attr): attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__')) uppercase_attr = dict((name.upper(), value) for name, value in attrs) return type(future_class_name, future_class_parents, uppercase_attr)
If we apply all the OOP technique (like the super keyword, calling to base __new__ and applies the convention names such as "cls", "base" and etcc..), then we can get the following code .
class UpperAttrMetaclass(type): def __new__(cls, name, bases, dct): attrs = ((name, value) for name, value in dct.items() if not name.startswith('__')) uppercase_attr = dict((name.upper(), value) for name, value in attrs) return super(UpperAttrMetaclass, cls).__new__(cls, name, bases, uppercase_attr)
So in a conclusion, about __metaclass__
indeed, metaclasses are especially useful to do black magic, and therefore complicated stuff. But by themselves, they are simple:
- intercept a class creation
- modify the class
- return the modified class
why the hell would you use metaclass?
class Person(models.Model): name = models.CharField(max_length=30) age = models.IntegerField()
guy = Person(name='bob', age='35') print guy.age
IntegerField
object. It will return an int
, and can even take it directly from the database.
models.Model
defines __metaclass__
and it uses some magic that will turn the Person
you just defined with simple statements into a complex hook to a database field.
the last word:
Everything is an object in Python, and they are all either instances of classes or instances of metaclasses.
- monkey patching
- class decorators
发表评论
-
python defining functions and calling functions
2013-04-02 16:19 693Python actually allow very fl ... -
python - trick to load kerberos urllib2
2012-10-17 11:49 0Currently there is a bug that k ... -
python - get the modification time and creation time of a file
2012-09-12 12:12 873as in Unix, you know that the c ... -
Use of Python metaclass II - Python Enumeration
2012-07-02 15:00 976In my previous post, I disusses ... -
Use of Python metaclass I - __getattr__ for static/class variable
2012-07-02 14:25 1319In my previous post, I disusses ... -
The module startup script
2012-06-27 12:00 0In my previous post. I discusse ... -
Recommended way to organize the Python project base
2012-06-26 18:24 340This article shows with example ... -
Python subprocess example1
2012-06-04 15:49 1049This article is based on the of ... -
Python Initialise a list to a specific length
2012-06-01 18:28 932Below show some tricks that y ... -
Python Format String Specification
2012-06-01 17:38 2601Since it is very common that yo ...
相关推荐
opencv_python-4.1.0.25-cp37-cp37m-linux_armv7l.whl
onnxruntime-1.13.1-cp38-cp38-win_amd64.whl
Few-shot CIFAR100数据集,来自CIFAR100数据集。 数据集共包含100类别,每个类别600张图像,合计60,000张图像。 数据集介绍:分为训练集、验证集、测试集 --data--train--:60个文件夹,36,000张图片 --data--val--: 20个文件夹,12,000张图片 --data--test--:20个文件夹,12,000张图片 FC100按照超类(Superclass)进行划分:训练集60个超类,验证集20个超类,测试集20个类别。
numpy-1.19.5-cp39-cp39-linux_armv7l.whl
基于springboot的城乡商城协作系统源码数据库文档.zip
基于springboot宠物管理系统源码数据库文档.zip
基于springboot餐饮连锁店管理系统源码数据库文档.zip
基于springboot在线问诊系统源码数据库文档.zip
1、资源内容地址:https://blog.csdn.net/2301_79696294/article/details/143734777 2、数据特点:今年全新,手工精心整理,放心引用,数据来自权威,且标注《数据来源》,相对于其他人的控制变量数据准确很多,适合写论文做实证用 ,不会出现数据造假问题 3、适用对象:大学生,本科生,研究生小白可用,容易上手!!! 4、课程引用: 经济学,地理学,城市规划与城市研究,公共政策与管理,社会学,商业与管理
功能说明: 陕理工图书馆管理系统包括两种用户,管理员,和学生用户。不同的用户都需要进行登录,然后针对其操作权限才能进入管理系统。 系统的设计将分为后台和前台,后台是系统管理员进行登录后管理,前台是学生使用的部分。 前台实现的功能包括:学生用户注册、登录,座位信息查看、阅览室信息、在线交流、座位预约、查看图书位置等。 服务器后台管理实现的功能包括:管理员登录,阅览室信息管理,座位管理,预约管理,图书管理以及用户管理等。 环境说明: 开发语言:python Python版本:3.6.8 数据库:mysql 5.7数据库工具:Navicat11开发软件:pycharm
numpy-1.16.1-cp35-cp35m-linux_armv7l.whl
scipy-1.2.0-cp35-cp35m-linux_armv7l.whl
opencv_python-4.0.1.24-cp37-cp37m-linux_armv7l.whl
ASP.NET酒店管理系统源码(WPF) 一、源码特点 采用WPF进行开发的酒店管理系统源码,界面相当美观,功能齐全 二、菜单功能 1、预订登记:可选择入住时间、离店时间、所在城市、证件类型,保存、删除、查询、返回 2、住宿结算:新增入住、保存、删除、查询、返回 3、今日盘点:查询、返回 4、查询统计: 5、房间管理:增加房间类型、删除类型、增加房间、删除房间、保存、返回 6、用户管理:增加用户、删除用户、保存、返回 7、系统配置:基本功能 8、显示当前系统时间等功能的实现
基于springboot的c语言学习辅导网站源码数据库文档.zip
基于springboot医疗废物管理系统源码数据库文档.zip
opencv_python-4.5.5.64-cp39-cp39-linux_armv7l.whl
gee_python基于机器学习ML(随机森林RF)的土地分类.ipynb
ta_lib-0.5.1-cp310-cp310-win32.whl
内容概要:本文档详细介绍了全国大学生电子设计竞赛的相关信息,包括竞赛的目的、流程、内容和技术要求等。竞赛涵盖了电子电路设计、嵌入式系统开发、信号处理等多个领域,通过竞赛可以有效提升学生的实践动手能力、创新意识和团队协作能力。 适合人群:准备参加全国大学生电子设计竞赛的学生及教师。 使用场景及目标:帮助学生和教师全面了解比赛的要求和流程,为备赛做好充分准备。 其他说明:文中提供了详细的竞赛内容介绍、技术要求、评审标准和注意事项,有助于参赛队伍制定合理的参赛策略,提高竞赛水平。