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>
从结果中可以看出,一个对象从创建到被调用的大致过程:
- __new__是我们通过类名进行实例化对象时自动调用的
- __init__是每一次在实例化对象之后调用的
- __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的实例对象,同时还是可调用对象,因此就可以想调用函数一样调用它