最近研究这三个函数的使用,或者说较为容易遇到,但是很容易混淆的。
首先要明白在python里面函数就是一个对象。而新建一个函数都是需要一定步骤的。而里面具有很多私有化的函数,都是在底层默认调用实现。而有时候有需求就需要自己重写(个性化定制)。
开始前要有一个这样的对象建立的概念:
先有创建,才有初始化。然后使用中实例化对象后在被。即先__new__,而后__init__,最后__call__。
# 构造方法:__init__():
初次接触到python面向对象时候第一个就是__init__,用于告诉编译器相关函数或变量仅用于初始化。而为什么一定要定义它?
首先看如何写:
class foo():
'''
进行初始化
'''
def __init__(self, name, age):
self.name = name
self.age = age
def people(self):
return f'{self.name}的年龄是{self.age}'
#新建一个对象
f = foo('bill', 12)
#bill的年龄为12
print(f.people())
#如果想更改bill的年龄:
#更改bill的年龄为23
f.age = 21
#更改过来没?自己试试
print(f.people())
可以看到,__init__就是给对象f绑定属性,然后通过对象去改变属性,如果没有这个,那么点语法,是无法生效的。初始化绑定属性。但是当实例化一个类的时候, __init__并不是第一个被调用的, 第一个被调用的是__new__
#新建函数 __new__
1 继承自object的新式类(元类了解一下)才有__new__ .
2 __new__至少要有一个参数cls,代表当前类,此参数在实例化时由Python解释器自动识别
3 在任何新式类的__new__()方法,不能调用自身的__new__()来制造实例,因为这样会造成死循环,如果当前类中没有重写__new__方法,那么就追溯到父类,一直到object基类。
4 使用我object或者没有血缘关系的新式类的__new__是安全的,但是如果是在有继承关系的两个类之间,应该避免互相调用造成死循环.(子类父类互相调用)
5 我们在使用时,尽量使用__init__函数,不要去自定义__new__函数,因为这两者在继承派生时的特性还是很不一样的。
#回调函数__call__ :
先看没有__call__时候怎么改变属性值
#没有__call__
class Student():
#初始化类
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
#格式化输出
return f'{self.name}的年龄是{self.age}'
#实例化一个新的学生
student_1 = Student('bill', 12)
#打印学生信息
#如果没有__str__打印的是地址,有__str__那就返回的是自定义的语句
print(student_1) =>bill的年龄是12
#打印学生名字
print(student_1.name) #=> bill
#打印学生年龄
print(student_1.age) #=> 12
#但是我想更改年龄怎么办?
student_1.age = 34
#打印学生信息
print(student_1) #=>bill的年龄是34
#但是我想student_1(34)这样像函数一样调用,但是这样是不行的,是会报错的
有__call__后,又是怎么改变属性值
#新建一个类
class Student():
#进行初始化
def __init__(self, name, age, ):
self.name = name
self.age = age
def __call__(self, age):
self.age = age
def __str__(self):
return f'{self.name}的年龄是{self.age}'
#实例化一个学生出来
student1 = Student('bill', 12)
print(student1)
#现在进行年龄的更改,就可以象调用方法一样的调用了。
student1(34)
print(student1) #=> bill的年龄是34
有了__call__就可以把对象当作函数一样的调用了。也就是说__call__()的作用是使实例能够像函数一样被调用,同时不影响实例本身的生命周期(__call__()不影响一个实例的构造和析构)。但是__call__可以用来改变实例的内部成员的值。
#一个小的总结:
__new__: 对象的创建,是一个静态方法,第一个参数是cls。
__init__ : 对象的初始化, 是一个实例方法,第一个参数是self,初始化的时候就具有的属性,这个属性可以设默认值。
__call__ : 对象可被掉用,注意不是类,是对象。对象可以被调用,否则是不可以的,这里面的不能设默认值。