__str__:
如下代码,list是个类,People也是类,但是对象shuai打印出来是内存地址,而对象l打印出来的是l本身的信息
class People:
home = "china"
def __init__(self,name):
self.name = name
def talk(self):
print("hahaha")
shuai =People('shuai')
print(shuai) # 打印内存地址 <__main__.People object at 0x000001B67F676BA8>
l = [1,2,3]
print(l) # 打印l本身的信息 [1, 2, 3]
如上,也就是说class会有一种机制,能够让我们打印由一个类产生的对象时,能够打印出对象相关的信息,那就用到了内置的__str__()方法,这个绑定给对象的方法在打印的时候会触发,是默认触发的,就会打印出来内存地址,如上图的shuai
通过重写该方法,来自定义返回的内容
class People:
home = "china"
def __init__(self,name):
self.name = name
def talk(self):
print("hahaha")
def __str__(self):
return '自定义内容'
shuai = People('shuai')
print(shuai) # 自定义内容
如果不写返回的内容,提示返回了一个不是字符串的类型,所以知道,它必须返回字符串类型
class People:
home = "china"
def __init__(self,name):
self.name = name
def talk(self):
print("hahaha")
def __str__(self):
pass
shuai = People('shuai')
print(shuai) # TypeError: __str__ returned non-string (type NoneType)
__del__:
如下代码,对象f产生后,就会在内存中,知道文件关闭被释放掉,或者执行del 删除掉
class Test:
def __init__(self, x):
self.num = x
f = Test(5)
print(f.num)
del f
内置函数__del__(),会在整个程序执行完后,触发对象的绑定方法__del__(),通常该方法用来写一些清理操作
在使用del时,del删除完成后,会触发__del__()
class Test:
def __init__(self, x):
self.num = x
def __del__(self):
print("执行del")
f = Test(5)
# del f # 执行del
print(f.num)
# 5
# 执行del
如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义__del__,如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源,比如(打开一个文件,创建一个数据库链接),则必须在清除对象的同时回收系统资源,这就用到了__del__,通过重写__del__ 来进行其他操作
典型的应用场景:
创建数据库类,用该类实例化出数据库链接对象,对象本身是存放于用户空间内存中,而链接则是由操作系统管理的,存放于内核空间内存中
当程序结束时,python只会回收自己的内存空间,即用户态内存,而操作系统的资源则没有被回收,这就需要我们定制__del__,在对象被删除前向操作系统发起关闭数据库链接的系统调用,回收资源
f=open('a.txt') #做了两件事,在用户空间拿到一个f变量,在操作系统内核空间打开一个文件
del f #只回收用户空间的f,操作系统的文件还处于打开状态
#所以我们应该在del f之前保证f.close()执行,即便是没有del,程序执行完毕也会自动del清理资源,于是文件操作的正确用法应该是
f=open('a.txt')
# 读写...
f.close()
# 很多情况下大家都容易忽略f.close,这就用到了with上下文管理
__getitem__、__setitem__、__delitem__:
如下代码,l是一个对象,d是一个对象,l[1]就是访问对象的一个熟悉,d["name"]也是访问对象的一个属性,但是通常访问对象的属性都是:obj.name 这种形式的
l = [1,2,3]
d = {"name": "bone"}
print(l[1]) # 2
print(d["name"]) # bone
如上,说明python中有支持中括号形式访问对象属性的方法
正常访问一个对象的属性
class Test:
def __init__(self, name ,age):
self.name = name
self.age = age
f = Test("shuai", 18)
print(f.name) # shuai
print(f.age) # 18
1、实现使用中括号形式访问属性,需要重写__getitem__
class Test:
def __init__(self, name ,age):
self.name = name
self.age = age
def __getitem__(self, item):
print(self)
print(item)
print(type(item))
f = Test("shuai", 18)
print(f.name) # shuai
print(f.age) # 18
# 上面打印没有触发__getitem__方法,需用通过【】形式触发
f["name"] # <__main__.Test object at 0x000002AB74A1D438> name <class 'str'>
上面f["name"]拿到的是字符串name,不是变量name的值,那就可以用反射来实现
class Test:
def __init__(self, name ,age):
self.name = name
self.age = age
def __getitem__(self, item):
# return getattr(self,item)
return self.__dict__[item]
f = Test("shuai", 18)
# print(f["name"]) # shuai
print(f["name"]) # shuai
2、实现[]设置属性,__setitem__()
class Test:
def __init__(self, name ,age):
self.name = name
self.age = age
def __getitem__(self, item):
# return getattr(self,item)
return self.__dict__[item]
def __setitem__(self, key, value):
# setattr(self, key, value)
self.__dict__[key] = value
f = Test("shuai", 18)
print(f["name"]) # shuai
print(f.__dict__) # {'name': 'shuai', 'age': 18}
f["name"] = "nb"
print(f.__dict__) # {'name': 'nb', 'age': 18}
3、实现[]删除属性,__delitem__()
class Test:
def __init__(self, name ,age):
self.name = name
self.age = age
def __getitem__(self, item):
# return getattr(self,item)
return self.__dict__[item]
def __setitem__(self, key, value):
setattr(self, key, value)
self.__dict__[key] = value
def __delitem__(self, key):
# delattr(self,key)
self.__dict__.pop(key)
f = Test("shuai", 18)
print(f["name"]) # shuai
print(f.__dict__) # {'name': 'shuai', 'age': 18}
f["name"] = "nb"
print(f.__dict__) # {'name': 'nb', 'age': 18}
del f["name"]
print(f.__dict__) # {'age': 18}
还有很多类似上面的方法。。。。。。。。。。。。。
所有的比如字符串、列表等等的内置方法,都支持上面的操作,重写自定义