关于__init__,以及__new__,__call__的基本认识

最近研究这三个函数的使用,或者说较为容易遇到,但是很容易混淆的。

首先要明白在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__ : 对象可被掉用,注意不是类,是对象。对象可以被调用,否则是不可以的,这里面的不能设默认值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值