python中__new__, __init__, __call__的用法

python3中的所有类都继承object类,因此可以不用显示的指定基类. object基类中拥有的方法和属性可通用于所有类

概述

在进行详细介绍之前,先要有一个直观的认识

  • __new__负责对象的创建, 而__init__负责对象的初始化;
  • __new__是一个类方法, 而__init__和__call__是一个对象方法
  • __call__声明这个对象是可调用的(callable)
class Test:
    def __new__(cls):
        print("Test.__new__")
        return super().__new__(cls)
    def __init__(self):
        print("Test.__init__")
    def __call__(self, *args):
        print("Test.__call__ args:", args)
        
a = Test()
a('arg1', 'arg2')

# 输出结果
Test.__new__
Test.__init__
Test.__call__ args: ('arg1', 'arg2')

从这个结果中我们可以得出,创建一个对象时,会先调用__new__方法实例化对象,再调用__init__方法初始化对象

__new__方法

__new__是构造函数,负责对象的创建,它需要返回一个实例

class Test:
    def __new__(cls):
        print("Test.__new__")
    def __init__(self):
        print("Test.__init__")
        
b = Test()
print(b)

# 输出结果
Test.__new__
None

从结果上看,b被判定为None, 因为我们没有在__new__类方法中返回对象.
现在我们来做一个实验,在__new__方法中返回一个其他对象,会发生声明呢?

class Test:
    def __new__(cls):
        print("Test.__new__")
        return 10
    def __init__(self):
        print("Test.__init__")
        
b = Test()
print(b)

# 输出结果
Test.__new__
10

这意味着完全可以通过重写__new__方法来控制类对象的实例化过程

__init__方法

__init__是一个初始化函数,负责对__new__实例化的对象进行初始化,不允许有返回值

class Test:
    def __init__(self):
        print("Test.__init__")
        return 3.0
        
c = Test()
print(c)

# 输出结果
Test.__init__
TypeError: __init__() should return None, not 'float'

__init__方法中除了self定义的参数,其他参数都必须于__new__方法中除cls参数外的参数保持一致或者等效

class Test:
    def __new__(cls, *args, **kwargs):
        print("new", args, kwargs)
        return super().__new__(cls)
    def __init__(self, *args, **kwargs):
        print("init", args, kwargs)
        
c = Test('arg1', 'arg2', a=1, b=2)
print(c)

# 输出结果
new ('arg1', 'arg2') {'a': 1, 'b': 2}
init ('arg1', 'arg2') {'a': 1, 'b': 2}
<__main__.Test object at 0x10f74ad50>

对象的创建过程

为了弄清楚创建一个对象的整个过程,再看下面一个例子

class Test:
    def __new__(cls, *args, **kwargs):
        print("Test.__new__", args, kwargs)
        self = super().__new__(cls)
        print(self)
        return self
    
    def __init__(self, *args, **kwargs):
        print("Test.__init__", args, kwargs)
        print(self)
        
c = Test('arg1', 'arg2', a=1, b=2)
print(c)

# 输出结果
Test.__new__ ('arg1', 'arg2') {'a': 1, 'b': 2}
<__main__.Test object at 0x10f756950>
Test.__init__ ('arg1', 'arg2') {'a': 1, 'b': 2}
<__main__.Test object at 0x10f756950>
<__main__.Test object at 0x10f756950>

从结果中可以看出,一个对象从创建到被调用的大致过程:

  1. __new__是我们通过类名进行实例化对象时自动调用的
  2. __init__是每一次在实例化对象之后调用的
  3. __new__方法创建一个实例之后返回这个实例对象,并将其传递给__init__方法的self参数

__call__方法

首先来了解下python的内置函数callable.

  • 如果callable的对象参数显示为可调用,则返回True,否则返回False;
  • 如果返回True, 则调用仍然有可能失败;
  • 如果返回False, 则调用对象永远不会成功

一般来说,自定义的函数,类,内置函数都属于可调用对象。也就是可以把括号"()"应用到某个对象身上,都称之为可调用对象。

def func(name):
    print(f"this is my {name}")
    
print(callable(filter))
print(callable(max))
print(callable(object))
print(callable(func))
print(callable(callable))
print(callable("test"))

__call__的左右就是声明这个类的对象是可调用的。即实现了类的__call__方法之后,用callable调用这个类对象时,结果为True。

class Test1:
    pass

a = Test1()
print(callable(a))  # False

class Test2:
    def __call__(self, *args):
        print("__call__ function, args", args)

b = Test2()
print(callable(b)) # True
b('arg1', 'arg2') # __call__ function, args ('arg1', 'arg2')

由于实现了__call__方法,b是Test2的实例对象,同时还是可调用对象,因此就可以想调用函数一样调用它

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值