构造和初始化

简介: 构造和初始化

__new__是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例,是个静态方法。

__init__是当实例对象创建完成后被调用的,然后设置对象属性的一些初始值。

故而“ 本质上 ”来说,__new__()方法负责创建实例,而__init__()仅仅是负责实例属性相关的初始化而已,执行顺序是,先new后init。

class Student(object):
    def __new__(cls,*args,**kwargs):
        print('我是new函数!')   #这是为了追踪new的执行过程
        print(type(cls))        #这是为了追踪new的执行过程
        return object.__new__(cls)  #调用父类的(object)的new方法,返回一个Student实例,这个实例传递给init的self参数
    def __init__(self,name,age):
        self.name=name
        self.age=age
        print('我是init')
    def study(self):
        print('我爱学习!')
if __name__=='__main__':
    s=Student('张三',25)
    print(s.name)
    print(s.age)
    s.study()

运行结果为:

我是new函数!
<class 'type'>
我是init
张三
25
我爱学习!

1.2. 属性访问控制

通常情况下,我们在访问类或者实例对象的时候,会牵扯到一些属性访问的魔法方法,主要包括:

getattr (self, name): 访问不存在的属性时调用

getattribute (self, name):访问存在的属性时调用(先调用该方法,查看是否存在该属性,若不存在,接着去调用①)

setattr (self, name, value):设置实例对象的一个新的属性时调用

delattr (self, name):删除一个实例对象的属性时调用 一个例子

class Foo:
    x=1
    def __init__(self,y):
        self.y=y
    def __getattr__(self, item):
        print('----> from getattr:你找的属性不存在')
    def __setattr__(self, key, value):
        print('----> from setattr')
        # self.key=value #这就无限递归了,你好好想想
        self.__dict__[key]=value #应该使用它
    def __delattr__(self, item):
        print('----> from delattr')
        # del self.item #无限递归了
        self.__dict__.pop(item)
    def __getattribute__(self, item):
        print('----> __getattribute__')
        return super().__getattribute__(item)
#__setattr__添加/修改属性会触发它的执行
f1=Foo(10)
print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
f1.z=3
print(f1.__dict__)
#__delattr__删除属性的时候会触发
f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__)
#__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx

输出

----> from setattr
----> __getattribute__
----> __getattribute__
{'y': 10}
----> from setattr
----> __getattribute__
----> __getattribute__
{'y': 10, 'z': 3}
----> __getattribute__
----> from delattr
----> __getattribute__
----> __getattribute__
{'y': 10, 'z': 3}
----> __getattribute__
----> from getattr:你找的属性不存在

注意,调用

self.__dict__[key]=value

会触发

def __getattribute__(self, item):
        print('----> __getattribute__')
        return super().__getattribute__(item)

因为 虽然是要给字典self.__dict__添加键值对,其中隐含着首先获得self.__dict__。 另外__getattribute__需要返回super().__getattribute__(item),否则函数默认返回None,报错。

相关文章
|
2天前
|
数据安全/隐私保护 C++
C++ 构造函数实战指南:默认构造、带参数构造、拷贝构造与移动构造
C++中的构造函数是特殊成员函数,用于对象初始化。类型包括默认构造函数(无参数)、带参数构造函数、拷贝构造函数和移动构造函数。默认构造函数设置对象默认状态,带参数构造函数允许传递初始化值。拷贝构造函数复制已有对象,移动构造函数高效转移资源。构造函数的访问权限可控制为public、private或protected。理解构造函数有助于编写健壮的C++代码。关注公众号`Let us Coding`获取更多内容。
20 0
|
2月前
|
索引
初始化数组
【2月更文挑战第2天】初始化数组。
14 3
|
3月前
|
C语言
C11中类成员变量定义时初始化问题
C11中类成员变量定义时初始化问题
28 0
|
10月前
|
Java 编译器
对象的构造及初始化
对象的构造及初始化
59 0
指针的介绍,定义,初始化
每个变量都有自己的地址,地址也是数据,就用地址类型的变量来装,地址类型就叫做指针类型,即指针类型定义的变量就是专门装地址的。
112 0
|
网络安全 数据安全/隐私保护
M12-2 初始化
M12-2 初始化
99 0
|
数据库 C++
确定对象使用前已先被初始化
确定对象使用前已先被初始化
139 0
|
算法 安全 Java
深入理解 NioEventLoopGroup初始化
深入理解 NioEventLoopGroup初始化
129 0