前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python自学成才之路 详解类的三个重要方法__new__,__init__,__call__

Python自学成才之路 详解类的三个重要方法__new__,__init__,__call__

作者头像
我是李超人
发布2020-08-20 20:02:47
3200
发布2020-08-20 20:02:47
举报
文章被收录于专栏:大数据入坑指南

文章目录
  • __call__方法
  • __new__和__init__

这里对类做两种划分,元类和普通类(基类中不包含type)。

__call__方法

首先介绍一下__call__方法,python中要想一个类的对象能够像函数一样被调用,那这个类需要实现__call__方法。比如像下面这样:

代码语言:javascript
复制
class Person(object):

    def __call__(self):
        print('__call__')


person = Person()
person()

__call__方法中也可以传递参数

代码语言:javascript
复制
class Person(object):

    def __call__(self, behavior: str):
        print('__call__: ' + behavior)


person = Person()
person('hello')

__call__也可以返回值

代码语言:javascript
复制
class Person(object):

    def __call__(self, behavior: str):
        print('__call__: ' + behavior)
        return 'world'


person = Person()
res = person('hello')
print(res)

其实元类和普通类的__call__方法没什么区别,都是为了让对象能被调用,普通类的对象被调用很好理解,元类的对象被调用是个什么情况呢?前面说过,元类的对象实际上是类实例(元类是用来创建类),那元类的对象被调用形式上又是怎么样的?是不是就是就是’类()‘这种形式,所以此处的Person()就是元类的对象被调用了,他返回的是一个实例。

new__和__init

这两个方法看名字就能知道意思,第一个一定是创建一个对象,第二个就是对对象做初始化用的。元类和普通类这两个方法的作用也是一样的。看下面这个例子:

代码语言:javascript
复制
class Person(object):

    def __new__(cls, *args, **kwargs):
        print('Demo __new__')
        return super(Person, cls).__new__(cls)

    def __init__(self, name, age):
        print('Demo __init__')
        self.name = name
        self.age = age

    def __call__(self, behavior: str):
        print('Demo __call__ : ' + behavior)

person = Person(name='perter', age=18)
person('hello')

方法__new__中产生person实例,此时实例没有任何属性,__init__方法为person实例添加属性。

注意:__new__中的参数一般是用cls,cls表示类本身,在__new__中还没有实例对象。__init__中用的self,self表示实例,此时对象已经产生了。

上面其实介绍的都是普通类的__new__, init, __call__方法,实际上元类这三个方法的含义和普通类是一样的,只是元类的实例是类,所以元类这三个方法的作用依次是 new:创建元类对象(类实例) init:对元类对象做初始化,这里的初始化和普通类的初始化不太一样后面会介绍 call:其类实例创建对象实例时被调用,返回类实例的对象实例

元类的完整案例

代码语言:javascript
复制
class MetaClass(type):

    # 第一步
    def __new__(mcs, *args, **kwargs):
        print('MetaClass __new__')
        return super(MetaClass, mcs).__new__(mcs, *args, **kwargs)

    # 第二步
    def __init__(cls, *args, **kwargs):
        print('MetaClass __init__')
        super(MetaClass, cls).__init__(*args, **kwargs)

    # 第三步
    def __call__(cls, *args, **kwargs):
        print('MetaClass __call__')
        return super(MetaClass, cls).__call__(*args, **kwargs)


class Person(metaclass=MetaClass):

    gender = 'man'

    # 第四步
    def __new__(cls, *args, **kwargs):
        print('Demo __new__')
        return super(Person, cls).__new__(cls)

    # 第五步
    def __init__(self, name, age):
        print('Demo __init__')
        self.name = name
        self.age = age

    # 第六步
    def __call__(self, behavior: str):
        print('Demo __call__ : ' + behavior)

    def say(self):
        pass


person = Person(name='perter', age=18)
person('hello')

输出:
MetaClass __new__
MetaClass __init__
MetaClass __call__
Demo __new__
Demo __init__
Demo __call__ : hello

第一步:创建类实例,并返回类实例 第二步:初始化类实例 第三步:执行Person(name=‘perter’, age=18)时被调用,创建类实例的对象实例,并返回对象实例 第四步:其实第三步是通过第四步和第五步来执行的,第四步是创建对象实例 第五步:对象实例初始化,添加person,age属性 第六步:执行person(‘hello’)被调用

感兴趣的童鞋可以debug一下上面的案例,你会发现元类里面的__new__和__init__这两个方法除了第一个参数不一样之外,后面两个参数值是完全一样的,其实通过__new__方法已经把完整类实例创建好了,那__init__方法到底可以做什么?

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/07/16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • __call__方法
  • new__和__init
相关产品与服务
日志服务
日志服务(Cloud Log Service,CLS)是腾讯云提供的一站式日志服务平台,提供了从日志采集、日志存储到日志检索,图表分析、监控告警、日志投递等多项服务,协助用户通过日志来解决业务运维、服务监控、日志审计等场景问题。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档