前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python 中的元类详解

python 中的元类详解

作者头像
Tim在路上
发布2020-08-04 22:24:36
7060
发布2020-08-04 22:24:36
举报

在其他语言中我们都知道类和int,string等类型一样是用来生成对象的。 类就是生成对象的代码段。 在python中任然是这样,但是Python中的类还远不止如此,在python中类也是对象。只是这个对象拥有创建对象的能力。

但是,它的本质仍然是一个对象,于是乎你可以对它做如下的操作:

  1. 你可以将它赋值给一个变量
  2. 你可以拷贝它
  3. 你可以为它增加属性
  4. 你可以将它作为函数参数进行传递

同时因为类就是对象,所以可以在运行时动态的创建。

代码语言:javascript
复制
def choose_class(name):
…       if name == 'foo':
…           class Foo(object):
…               pass
…           return Foo     # 返回的是类,不是类的实例
…       else:
…           class Bar(object):
…               pass
…           return Bar
…
>>> MyClass = choose_class('foo')
>>> print MyClass              # 函数返回的是类,不是类的实例
<class '__main__'.Foo>
>>> print MyClass()            # 你可以通过这个类创建类实例,也就是对象
<__main__.Foo object at 0x89c6d4c>

由于类也是对象,所以它们必须是通过什么东西来生成的才对。当你使用class关键字时,Python解释器自动创建这个对象。

使用type来创建类

我们都知道python中的自身,使用type可以知道当前变量的类型

代码语言:javascript
复制
print type(1)
<type 'int'>
print type("1")
<type 'str'>

type可以这样使用

代码语言:javascript
复制
type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))

比如用type来创建下面的一个类

代码语言:javascript
复制
class Foo(object):
    bar = True

使用type简化创建

代码语言:javascript
复制
Foo = type('Foo', (), {'bar':True})

使用继承, 在创建一个下面的子类

代码语言:javascript
复制
class FooChild(Foo):
…       pass
代码语言:javascript
复制
FooChild = type('FooChild', (Foo,),{})
print FooChild
<class '__main__.FooChild'>
print FooChild.bar   # bar属性是由Foo继承而来
True

使用type为你的类增加方法

代码语言:javascript
复制
def echo_bar(self):
        print self.bar

FooChild = type('FooChild', (Foo,), {'echo_bar': echo_bar})
hasattr(Foo, 'echo_bar')
False
hasattr(FooChild, 'echo_bar')
True
my_foo = FooChild()
my_foo.echo_bar()
True

已定义的元类

==type==就是Python在背后用来创建所有类的元类。除此外还有==str==,==int==等内件元类

创建自己的元类

你可以在写一个类的时候为其添加metaclass属性。

代码语言:javascript
复制
class Foo(object):
    __metaclass__ = something…

Foo中有metaclass这个属性吗?如果是,Python会在内存中通过metaclass创建一个名字为Foo的类对象。如果Python没有找到metaclass,它会继续在Bar(父类)中寻找metaclass属性,并尝试做和前面同样的操作。如果Python在任何父类中都找不到metaclass,它就会在模块层次中去寻找metaclass,并尝试做同样的操作。如果还是找不到metaclass,Python就会用内置的type来创建这个类对象。

比如将属性全部转化为大写

代码语言:javascript
复制
# 元类会自动将你通常传给‘type’的参数作为自己的参数传入
def upper_attr(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)
 
    # 通过'type'来做类对象的创建
    return type(future_class_name, future_class_parents, uppercase_attr)
 
__metaclass__ = upper_attr  #  这会作用到这个模块中的所有类
 
class Foo(object):
    # 我们也可以只在这里定义__metaclass__,这样就只会作用于这个类中
    bar = 'bip'

Python中的一切都是对象,它们要么是类的实例,要么是元类的实例,除了type。type实际上是它自己的元类。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用type来创建类
  • 已定义的元类
  • 创建自己的元类
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档