1.什么是魔法函数
以__开始和结束,不需要专门调用,在特定场合下,python会自己调用,如__init__, __str__等
2.常用的魔法函数
__str__: 返回类对象友好的提示,例子
class Test:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
obj = Test(name="Hello, World")
print(obj)
__len__:计算对象容器中元素的个数 # 应用场景???,将类当容器处理
class TestLen:
def __init__(self, mylist):
self.mylist = mylist
def __len__(self):
return len(self.mylist)
obj = TestLen([1,2,3,4])
print(len(obj)) # 去掉__len__, 则报错
__setitem__(新建字典),__getitem__(通过key获取value),__delitem__(删除key对应的value),应用场景,将类当字典处理
class TestNewClass:
# 不会调用
def __get__(self, instance, owner):
print("get")
def __set__(self, instance, value):
print("set")
def __delete__(self, instance):
print("delete")
obj = TestNewClass()
# 不会调用get,set,delete方法
obj.name = "hyh"
print(obj.name)
del obj.name
print(obj.name) # 报错
新式类__get__,set,delete,达到上面效果,但是为啥不调用get,set,delete
参考:https://zhuanlan.zhihu.com/p/356076165
class TestDict:
def __init__(self):
self.dict = {}
# 新建字典
def __setitem__(self, key, value):
self.dict[key] = value
# 通过字典key获取value
def __getitem__(self, item):
return self.dict[item]
# 删除对应key的记录
def __delitem__(self, key):
del self.dict[key]
obj = TestDict()
obj.dict["name"] = "hyh" # 调用__setitem__
obj["age"] = 18 # 效果同上
print(obj.dict)
print(obj["name"]) # 调用__getitem__
del obj["age"] # 调用__delitem__
print(obj.dict)
__iter__,__next__:迭代器 ,将类对象当作可迭代对象
class TestIterator:
def __init__(self, value):
self.start = 0
self.end = value
def __iter__(self):
return self
def __next__(self):
if self.start < self.end:
self.start += 1
return self.start
else:
raise StopIteration
obj = TestIterator(5)
# 可遍历
for i in obj:
print(i)
# 使用next函数遍历
#print(next(obj))
#print(next(obj))
__enter__,__exit__:实现with上下文管理
class TestWith:
def __init__(self, filename, mode="r", encoding="utf-8"):
self.filename = filename
self.__file = open(filename, mode, encoding=encoding)
def __enter__(self):
print("enter")
return self
def write(self, content):
print("write")
self.__file.write(content)
def __exit__(self, exc_type, exc_val, exc_tb):
print("exit")
self.__file.close()
with TestWith(r"E:\python_apps\bk-pipline\haoyong_test\hyh.txt", mode="w", encoding="utf-8") as f:
f.write("nihao\n hello world")
实现数据库连接释放
import pymysql
import time
class TestConMysql:
def __init__(self, host, port, account, passwd, dbname):
self.host = host
self.port = port
self.account = account
self.passwd = passwd
self.dbname = dbname
self.conn = None
def __enter__(self):
print("打开连接")
self.conn = pymysql.connect(host=self.host,user=self.account,passwd=self.passwd,db=self.dbname, charset="utf8")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("关闭连接")
self.conn.close()
def cmd(self):
cursor = self.conn.cursor()
exe = cursor.execute("show databases")
time.sleep(30)
with TestConMysql(host="192.168.226.128", port=3306, account="root", passwd="111111", dbname="xxxx") as con:
con.cmd()
登录数据库查看连接数
__init__类实例化对象时被调用
class TestInit:
def __init__(self, name):
print(name)
obj = TestInit(name="hyh")
__new__负责创建类,在__init__之前执行
class TestNew:
#创建类
def __new__(cls, *args, **kwargs): #cls参数有python解释器提供
print("优先执行")
instance = super().__new__(cls) # 使用super创建类
print(id(instance))
return instance # 必须有返回值
#初始化类
def __init__(self, name):
print(name)
print(id(self))
__call__实现类对象像普通函数那样可调用
class TestCall:
def __init__(self, name):
self.name = name
def __call__(self, age):
print(f"我叫{self.name}, 今年{age}岁")
call = TestCall(name="hyh")
call(22)
__lt__实现对象可比较,应用场景,比较,排序对象
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return self.name + ":" + str(self.age)
def __lt__(self, other):
return self.age < other.age
people1 = People("hyh", 18)
people2 = People("hyh1", 19)
print(people1 > people2) # False