不知道大家在学习python的时候有没有遇到过这几个方法,我最近看了一下,下面这是我的理解
首先,先来说说__init__,这是一个初始化函数,是对你定义的类进行初始化的,对比我们的其他语言,是不是发现有什么区别,你不知道python的构造函数在哪。python类中的构造函数就是__new__了
class Some(object):
def __new__(cls, num):
print('__new__')
self = super().__new__(cls)
print(self)
return self
def __init__(self, num):
print('__init__')
self.num = num
print(self)
some = Some(213)
我们执行以下这个代码来看一下结果
__new__
<__main__.Some object at 0x000001F11830CF98>
__init__
<__main__.Some object at 0x000001F11830CF98>
可以看到__new__函数是在__init__函数之前执行的,并且将实例化的对象传给__init__,当然,如果__new__没有返回实例对象的话,__init__将不会执行,这个很容易理解,连对象都没有实例化又怎么会执行初始化方法呢
重写__new__能干什么
我们可以重写__new__来实现单例模式和工厂模式
首先我们先来看一下单例模式
单例模式是指创建唯一对象,单例模式设计的类只能实例化1个对象,通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源
class Some(object):
def __new__(cls, num):
if not hasattr(cls, '_instance'):
cls._instance = object.__new__(cls)
return cls._instance
def __init__(self, num):
self.num = num
some_one = Some(213)
some_two = Some(123)
print('some_one: ', some_one)
print('some_two: ', some_two)
运行一下看一下结果
some_one: <__main__.Some object at 0x0000017F3621CEB8>
some_two: <__main__.Some object at 0x0000017F3621CEB8>
两个指向了同一个地址,实现了单例模式,并且some_two实例里的num值会将some_one实例里的num值覆盖掉,这是因为又进行了一次初始化。
工厂模式
工厂模式包涵一个超类。这个超类提供一个抽象化的接口来创建一个特定类型的对象,而不是决定哪个对象可以被创建。
class Animal(object):
def __init__(self, animal):
self.animal = animal
def output(self):
print(self.animal)
class Car(object):
def __init__(self, car):
self.car = car
def output(self):
print(self.car)
class People(object):
def __init__(self, people):
self.people = people
def output(self):
print(self.people)
class Factory(object):
some = {"car": Car, "Animal": Animal}
def __new__(cls, name, other):
if name in cls.some.keys():
return cls.some[name](other)
else:
return People(other)
def __init__(self):
pass
some_one = Factory("Car", "Car")
some_one.output()
some_two = Factory("Animal", "Animal")
some_two.output()
some_three = Factory("People", "People")
some_three.output()
来看一下结果
Car
Animal
People
__call__能干什么
再说之前我们先来看一下callable()是干什么用的。我们平时自定义的函数、内置函数和类都属于可调用对象,但凡是可以把一对括号()应用到某个对象身上都可称之为可调用对象,判断对象是否为可调用对象就需要用到callable(),直接上代码
class Some(object):
def __init__(self, num):
self.num = num
def __call__(self, *args, **kwargs):
print("Yes, you do it!")
print(args)
some = Some(123)
print(callable(some))
some(123, 234)
看一下结果
True
Yes, you do it!
(123, 324)
很明显,实例化过后的对象some变成了一个可调用对象,并且我们还可以传入参数