Python从入门到实践:面向对象之内置方法六

Python的Class机制内置了很多特殊的方法来帮助使用者高度定制自己的类,这些内置方法都是以双下划线开头和结尾的,会在满足某种条件时自动触发。

1.__str__

str_方法会在对象被打印时自动触发,print功能打印的就是它的返回值,我们通常基于方法来定制对象的打印信息,该方法必须返回字符串类型

>>> class People:
...     def __init__(self,name,age):
...         self.name=name
...         self.age=age
...     def __str__(self):
...         return '<Name:%s Age:%s>' %(self.name,self.age) #返回类型必须是字符串
... 
>>> p=People('lili',18)
>>> print(p) #触发p.__str__(),拿到返回值后进行打印
<Name:lili Age:18>

2.__del__(析构函数)

del_会在对象被删除时自动触发。由于Python自带的垃圾回收机制会自动清理Python程序的资源,所以当一个对象只占用应用程序级资源时,完全没必要为对象定制_del_方法,但在产生一个对象的同时涉及到申请系统资源(比如系统打开的文件、网络连接等)的情况下,关于系统资源的回收,Python的垃圾回收机制便派不上用场了,需要我们为对象定制该方法,用来在对象被删除时自动触发回收系统资源的操作

class MySQL:
    def __init__(self,ip,port):
        self.conn=connect(ip,port) # 伪代码,发起网络连接,需要占用系统资源
    def __del__(self):
        self.conn.close() # 关闭网络连接,回收系统资源
 
obj=MySQL('127.0.0.1',3306) # 在对象obj被删除时,自动触发obj.__del__()

3.__init__

init()方法 当使用类名()创建对象时,Python解释器会自动执行以下操作:

A.为对象在内存中分配空间 创建对象

B.调用初始化方法为对象的属性设置初始值-初始化方法(init)

C.这个初始化方法是对象的内置方法,是专门用来定义一个类具有哪些属性的方法

4.__getattr__、__setattr__、__delattr__

之前介绍反射的时候说过,但是,这里有些许不同,内置方法里面没有hasattr

当使用obj.x = y的时候触发对象的setattr方法,当del obj.x的时候触发对象的delattr方法。
当尝试访问对象的一个不存在的属性时 obj.noexist 会触发getattr方法,getattr方法是属性查找中优先级最低的。
可以重写这3个方法来控制对象属性的访问、设置和删除
**特别注意:如果定义了getattr,而没有任何代码(即只有pass),则所有不存在的属性值都是None而不会报错,可以使用super().__getattr__()方法来处理**

class Student:
    def __getattr__(self, item):
        print('访问一个不存在的属性时候触发')
        return '不存在'

    def __setattr__(self, key, value):
        print('设置一个属性值的时候触发')
        # self.key = value  # 这样会无限循环
        self.__dict__[key] = value

    def __delattr__(self, item):
        print('删除一个属性的时候触发')
        if self.__dict__.get(item, None):
            del self.__dict__[item]

stu = Student()
stu.name = 'zlw'  # 设置一个属性值的时候触发
print(stu.noexit)  # 访问一个不存在的属性时候触发 , 返回'不存在'
del stu.name  # 删除一个属性的时候触发

5.__iter__、__next__

这2个方法用于将一个对象模拟成序列。内置类型如列表、元组都可以被选代,文件对象也可以被选代获取每一行内容。重写这两个方法就可以实现自定义的选代对象。

class MyRange():
    def __init__(self,begin,end,step):
        self.begin=begin
        self.end=end
        self.step=step
        self.count=0

    def __iter__(self):
        return self

    def __next__(self):
        if self.begin <self.end:
            self.count=self.begin
            self.begin=self.begin+self.step
            return self.count
        else:
            raise StopIteration('已经到达临界')

if __name__=='__main__':
    ra=MyRange(1,20,3)
    for item in ra:
        print(item)

----------------------------------------------------------------------------------------

6.item类和__len__

在深度学习中,我们在封装dataset的时候,一定会重写的两个内置方法,非常重要!!



class Person:

    def __getitem__(self,key):   # 获取
        return self.__dict__[key]

    def __setitem__(self,key,value):    #设置
        self.__dict__[key] = value

    def __delitem__(self,key):    #删除
        self.__dict__.pop(key)

p = Person()
p['a'] = 1
print(p['a'])
del p['a']
print(p['a'])    #这里会报KeyError

#使用len()时执行

class Life:
    def __init__(self,name,length):
        self.name = name
        self.length = length

    def __len__(self):
        return self.length

hsr = Life('hsr',100)
print(len(hsr))

7.__hash__

hash()用于获取一个对象(字符串、数字、对象)的哈希值,不能直接作用于list、set、dict

在hash()最用对象时,所得的结果不仅和对象的内容有关,还和对象的id(),也就是内存地址相关。

hash() 函数的对象字符不管有多长,返回的 hash 值都是固定长度的,也用于校验程序在传输过程中是否被第三方(木马)修改,如果程序(字符)在传输过程中被修改hash值即发生变化,如果没有被修改,则 hash 值和原始的 hash 值吻合,只要验证 hash 值是否匹配即可验证程序是否带木马(病毒)。

#对对象进行hash运算
class Student:
    def __init__(self,no,name):
        self.no = no
        self.name = name

    def __hash__(self):
        return hash(str(self.no)+self.name)

s = Student(102302,'hsr')
print(hash(s))

8.__eq__

class Life:
    def __init__(self,name,length):
        self.name = name
        self.length = length

    def __len__(self):
        return self.length

    def __eq__(self, other):
        return other.length == self.length  #重写后,判断的是长度是否相等,如果不重写,因为地址不一样,就不相等

hsr = Life('hsr',100)
ttt = Life('ttt',100)
print(hsr == ttt)

相关文章

学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习...
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面...
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生...
Can’t connect to local MySQL server through socket \'/v...
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 ...
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服...