魔术方法(内置方法)
# 类里面内置的双下划线开头的一些方法,他们具有特殊的功能,我们称之为魔术方法:简称魔术
"""魔术方法的学习只需要掌握每个方法什么时候触发或者执行就行了"""
1、__str__,__repr__方法
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
print('这是__str__')
# """__str__方法返回值必须是字符串类型"""
return 'name'
def __repr__(self):
print('__repr__')
return 'repr'
stu = Student('kevin', 18)
"""也就是说,__str__方法内部返回什么结果,打印的就是返回的结果,"""
print(stu) # 当打印或者输出对象的时候,会自动触发__str__的执行
# 这是__str__
# name
print(str(stu))
# 这是__str__
# name
print(repr(stu))
# __repr__
# repr
"""__repr__:它的功能和__str__一样,只不过,只写了他们两个其中之一,都会执行,但是,如果两个都写了,__str__它的优先级高于_repr__"""
# 我们一般用的是__Str__方法
2、__del__方法:
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
# 1. 当删除对象的时候,会自动触发函数的执行
# 2. 当程序结束的时候,也会自动触发执行
def __del__(self):
print('这是__del__')
stu = Student('kevin', 18)
print(stu.name) # kevin
print(stu.age) # 18
# 这是__del__
# 执行删除对象操作
del stu
# 这时候在打印stu对象就会报错了,报错信息为,没有找到stu这个名字,说明这个对象已经被删除掉了
# print(stu) # NameError: name 'stu' is not defined
"""__del__函数会在代码都走完以后再走__del__函数体内的代码"""
isinstance(obj,cla) and issubclass(sub,suoer) 使用方法
isinstance(obj,cla):
"""判断object是不是由这了class产生的,是的话返回True,不是的话返回False"""
class A:
pass
class B(A):
pass
a = A()
b = B()
print(isinstance(b, B)) # True
print(isinstance(a, B)) # False
"""它还可以用来判断一些数据类型"""
print(isinstance('hello', str)) # True
print(isinstance('hello', list)) # False
issubclass(sub,super):
"""判断一个class是否继承了;另一个class"""
class A:
pass
class B(A):
pass
print(issubclass(B, A)) # True
'判断B是否继承了A的类,返回的也是布尔值'
__doc__方法:
"""查看对这个class的一些解释说明信息,不能查看到注释信息"""
class Foo:
"""
author:kevin
date:2023-01-01
email:[email protected]
这是注释"""
def __init__(self):
"""这是初始化表对象"""
pass
class Bar(Foo):
# """这是Bar"""
pass
print(Foo.__doc__)
# author:kevin
# date:2023-01-01
# mail:[email protected]
# 这是注释
print(Bar.__doc__) # 这个特性不能够继承到父类
"""如果没有对这个class的解释说明就会返回None,如果有就会打印出来"""
__enter__ and __exit__
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print('代码走到了__enter__这里')
return '__enter__'
def __exit__(self, exc_type, exc_val, exc_tb):
print('代码走到了__exit__这里')
with Open('a.txt') as f:
print('代码走到了with open 这里')
print(f)
# 执行结果
# 代码走到了__enter__这里
# 代码走到了with open 这里
# 代码走到了__exit__这里
# __enter__
"""如果出现了with语句,就会立马触发__enter__的方法,如果有返回值就会把返回值赋给as后面的变量,
然后再执行with Open 的代码块,最后执行__exit__的代码块"""
情况二:
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print('代码走到了__enter__这里')
return '__enter__'
def __exit__(self, exc_type, exc_val, exc_tb):
print('代码走到了__exit__这里')
print(exc_type) # <class 'Exception'> 异常类型
print(exc_val) # 出现了错误 异常信息
print(exc_tb) # <traceback object at 0x000001DAB3D727C0> 追溯信息
# 如果我在这个地方return一个True就算下面出现了报错,代码还是会继续往下走,会直接忽略掉这个错误信息
return True
with Open('a.txt') as f:
print('代码走到了with open 这里')
raise Exception('出现了错误')
print('*' * 50)
# 未使用return
"""
Traceback (most recent call last):
File "D:\Program Files\Pycharm\pythonProject\import\exercise.py", line 2641, in <module>raise Exception('出现了错误')
Exception: 出现了错误
代码走到了__enter__这里
代码走到了with open 这里
代码走到了__exit__这里
<class 'Exception'>
出现了错误
<traceback object at 0x000002448CDE2700>
"""
# return 后
"""
代码走到了__enter__这里
代码走到了with open 这里
代码走到了__exit__这里
<class 'Exception'>
出现了错误
<traceback object at 0x0000029D11AC77C0>
**************************************************
"""
# return后代码就不会报错并且一直往下走
__setattr__,__delatter__,__getatter__
class Foo:
x = 1
def __init__(self, y):
self.y = y
def __getattr__(self, item):
print('这是__getattr')
def __setattr__(self, key, value):
# print(key, value) # z 1
# self.z = 1
# 你使用点语法,设置一个不存在的属性值就会自动触发__setattr__
# 错误使用
# self.key=value # 这就无限递归了,你好好想想
# 正确使用
self.__dict__[key] = value
# self.__dict__[key]=value #应该使用它
# super(Foo, self).__setattr__()
print('这是__setattr__')
def __delattr__(self, item):
print('这是__delattr__')
# 错误使用
# # del self.item #无限递归了
# 正确使用
self.__dict__.pop(item)
foo = Foo(10)
print(foo.y)
foo.z = 1
print(foo.z) # 1
del foo.z
print(foo.z)
# 如果不调用self.__dict__[key] = value方法,就看不到值
"""
这是__setattr__
这是__getattr
None
这是__setattr__
这是__getattr
None
"""
# 调用self.__dict__[key] = value方法后
"""
这是__setattr__
10
这是__setattr__
1
"""
# 使用删除方法后
"""
这是__setattr__
10
这是__setattr__
1
这是__delattr__
这是__getattr
None
"""
__setitem__,__getitem,__delitem__
class Foo(object):
def __init__(self, name):
self.name = name
def __getitem__(self, item):
print(item)
print("我执行了")
print(self.__dict__[item])
def __setitem__(self, key, value):
print("我也执行了")
print(key, value)
self.__dict__[key] = value
def __delitem__(self, key):
print('del obj[key]时,我执行')
self.__dict__.pop(key)
def __delattr__(self, item):
print('del obj.key时,我执行')
self.__dict__.pop(item)
obj = Foo('kevin')
# obj['name']
obj['age'] = 19
print(obj['age'])
del obj['age']
__call__
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
return 123
obj = Foo()
print(obj.__call__())
# __call__
# 123
"""对象加括号时会调用__call__的函数体"""
反射
反射就是通过字符串的形式来操作对象的属性
搭配的四种方法:
"""getattr() setattr() delattr() hasattr()"""
class Student():
school = 'SH'
def __init__(self, name, age):
self.name = name
self.age = age
def index(self):
print('Student.index')
stu = Student('jason', 20)
# print(stu.'name')]
# print(stu.name) # jason
"""这时候的name是str形式吗?很显然不是,那么我们要怎么做通过str形式来操作对象属性呢?"""
"""getattr() setattr() delattr() hasattr()"""
# 1、getattr()
res = getattr(stu, 'name')
print(res) # jason
'这时候的‘name’就是str形式了,可以看出来我们还是可以查看到对应的属性值'
res1 = getattr(stu, 'age', 666)
print(res1)
res2 = getattr(stu, 'age1', 666)
print(res2)
'如果查找的属性值存在就会得到对应的属性值,如果查找的属性值不存在就会新创建一个'
# jason
# 20
# 666
# 2、setattr()
setattr(stu, 'x', 66)
setattr(stu, 'name', 666)
print(stu.__dict__) # {'name': 666, 'age': 20, 'x': 66}
"""如果值存在就修改,不存在就添加"""
# 3、delattr()
delattr(stu, 'x')
print(stu.__dict__) # {'name': 666, 'age': 20}
"删除属性"
# 4、hasattr()
print(hasattr(stu, 'index')) # True
"只是一个判断是否存在,返回的是布尔值"
"补充"
import time
# time.sleep(3)
s = getattr(time, 'sleep')
print(s) # <built-in function sleep>
# 形式一
s(3) # 现在这个s具备了与sleep相同的功能了 time.sleep(3)
# 形式二
getattr(time, 'sleep')(3) # 这几种写法功能相等
time = __import__('time') # 以字符串的形式导入模块
# 这个地方的sleep遇到自己打出来pycharm不会再提示了
time.sleep(3)
random = __import__("random")
res = random.randint(0, 9)
print(res) # 3
反射的案例
class FtpServer:
def serve_forever(self):
while True:
inp = input('input your cmd>>: ').strip() # get a.txt put a.txt
cmd, file = inp.split() # get a.txt ['get', 'a.txt']
# hasattr(self, 'get')
# hasattr(self, 'put')
if hasattr(self, cmd): # 根据用户输入的cmd,判断对象self有无对应的方法属性
# getattr(self, ’get‘) get或者put的内存地址
func = getattr(self, cmd) # 根据字符串cmd,获取对象self对应的方法属性
func(file)
def get(self, file):
print('Downloading %s...' % file)
def put(self, file):
print('Uploading %s...' % file)
server = FtpServer()
server.serve_forever()
异常
1. 异常就是错误发生的信息,我们必须要做处理,否则,后续代码无法正常运行
2. 如何捕捉异常
try:
被检测的代码
except 异常类型:
pass
else:
print()
finally:
print()
"""以上结构是我们为了捕捉代码中出现的异常"""
3、自己抛出异常
class A:
def speak(self):
raise Exception('请先实现speak方法')
class B(A):
pass
b = B()
b.speak()
# 报错信息
"""
raise Exception('请先实现speak方法')
Exception: 请先实现speak方法
"""
4、自定义异常
必传参数'BaseException'
class MyException(BaseException):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return self.msg
raise MyException("这是异常信息")
标签:__,name,stu,Python,self,魔术,print,高阶,def
From: https://www.cnblogs.com/chao0308/p/17511971.html