魔法、反射、异常

魔术方法(内置方法)

魔术方法:类里面内置的双下划线开头的一些方法,他们具有一些特殊的功能,称之为魔术方法,简称魔法。(掌握每个方法什么时候执行)

1.__str__,__repr__方法

__str__方法:在打印或者输出对象时,才会被触发执行,此方法的内部返回值必须是字符串类型,return后面返回什么字符串,程序最后就打印什么结果

__repr__方法:功能与str一样,两者同时出现,支持str,因为str的优先级高于repr。

print是会执行两者中的一个,str()会执行__str__,repr()会执行__repr__

#1. __str__, __repr__方法
class Cake():e
    def __init__(self,price,size):
        self.price = price
        self.size =size
    """__str__:在打印或输出对象时,会被触发执行"""
    def __str__(self):
        print('from str')
        return '123' # 返回值必须是字符串类型,否则会报错!
                     # return返回什么字符串,程序最后打印就是什么字符串
    """__repr__: 功能和__str__一样,但是如果两者同时出现,只会执行__str__。"""
    def __repr__(self):
        print('from repr')
        return 'price1: %s' % self.price #  price1: 8 返回值必须是字符串类型,同 __str__一样

cake = Cake(8,320)
print(cake)
#结果为:from str
#       123

2.__del__方法

__del__方法:在程序结束运行时或者在删除对象时,都会自动触发执行。

作用: 清理垃圾数据。

class Cake():
    def __init__(self,price,size):
        self.price = price
        self.size =size
        self.f = open('a.txt','w',encoding='utf8')

    """__del__:在程序结束运行时会被触发执行、当删除对象时也会自动触发执行"""
    def __del__(self):
        print('from del')
        """可以做一些清理垃圾的操作"""

cake =Cake(6,200) # from del
del cake # from del

3.isinstance(obj,cls)和issubclass(sub,super)

isinstance(obj,cls):判断对象obj是否是由cls类产生的,或者判断数据类型
issubclass(sub,super): 判断 sub 是否是super的子类
#3. isinstance(obj,cls)和issubclass(sub,super)
class Animal():
    pass
class Cat(Animal):
    pass
cat =Cat()
'isinstance(obj,cls):判断对象obj是否是由cls类产生的,或者判断数据类型'
print(isinstance(cat, Cat))  # True ,对象cat ,是由Cat类产生的
print(isinstance("hi cat", str)) # True, 判断"hi cat"是不是字符串
'issubclass(sub,super): 判断 sub 是否是super的子类'
print(issubclass(Cat, Animal))  # True  查看Cat是不是Animal的子类

 4. __doc__方法

__doc__方法:查看类内部的注释,只能查看自己的注释,继承的父类的注释查看不了。

# 4.__doc__方法
class Foo():
    """
       author:huahua
       date:2023-05-20
       email:喵喵喵@163.com
       这是注释
    """
    pass

class Bar(Foo):
    """from Bar"""
    pass
a = Bar
print(a.__doc__) # from Bar

5.__enter__和__exit__

with:上下文管理器,可以自动打开、关闭文件。

__enter__:出现with语句,对象里的__enter__方法就会被触发,有返回值的话就会赋值给as 声明的变量。

__exit__:当with中的代码执行完毕时,才开始执行__exit__

当with代码块中出现异常,则在__exit__方法中会拿到异常的信息(异常类型、异常值、追溯信息)。

如果在__exit__方法中return True,则会忽略异常。

# 5.__enter__和__exit__
class Open():
    def __init__(self,name):
        self.name =name

    def __enter__(self):
        print('执行了enter')
        return 123

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with中代码块执行完毕时执行exit')
        print(exc_type)  # 异常类型 <class 'AttributeError'>
        print(exc_val)  # 异常值 ***着火啦,救火啊***
        print(exc_tb)  # 追溯信息 <traceback object at 0x0000022CEAF67888>
        # 当return True,则会正常执行完代码,直到走完程序,且exc_type、exc_val、exc_tb的返回值都为None
        # return True

with Open('a.txt') as f: # with语句出现,先执行 __enter__的代码体
    print('=====>执行代码块')# 再执行with语句中的代码
    print(f) # __enter__中的return返回值,赋值给了f
    raise AttributeError('***着火啦,救火啊***') # 当__exit__中有 return True时,raise不会抛出异常,程序正常执行
print('0'*100) # 不会执行

结果:

6. __getattr__,__setattr__,__delattr__

前提:必须使用点语法,对象.x

__getattr__:当找的属性不存在时,就会触发执行,并且有个参数:属性名

__setattr__:设置属性时,触发点语法,会自动触发__setattr__的执行,并且有两个参数:key,value。eg:self.__dict__[key]=value

__delattr__: 删除属性时会触发执行

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')
    def __delattr__(self, item):
        print('----> from delattr')

obj = Foo(20) #  from setattr
# obj.z # obj中并没有z这个属性,from getattr:你找的属性不存在
obj.z = 1 # from setattr
# print(obj.__dict__) # {},重新设置了obj的属性,所以里面什么也没有是个空字典
# obj.__dict__['z'] = 2
# print(obj.__dict__) #{'z': 2}
del obj.y # ----> from delattr

7.__getitem__,__setitem__,__delitem__

前提:必须使用中括号([ ]),对象['x']

__getitem__:用对象获取一个不存在属性时,会触发,有个参数:属性名

__setitem__: 当设置一个不存在的属性时,会触发,并且有两个参数:key,value, self.__dict__[key] = value

__delitem__:删除属性时,会触发

class Foo(object):
    def __init__(self, name):
        self.name = name

    def __getitem__(self, item):
        print(item) # age
        print("我执行了")
        print(self.__dict__[item]) # None
        
    def __setitem__(self, key, value):
        print("我也执行了") 
        print(key, value) # age 19
        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['age'] = 19    # 设置一个不存在的属性,触发__setitem__  ,我也执行了
print(obj['age']) # 查找属性
del obj['age'] # 删除属性

8. __call__

__call__:对象+()会触发类内部的__call__,如果有返回值,就会把返回值给对象+()

# __call__
class Foo:

    def __init__(self):
        pass

    def __call__(self, *args, **kwargs):
        print('__call__')
        return '123'

obj = Foo()

print(obj())  # 对象加括号  # __call__
                          # 123

反射

反射:通过字符串的形式来操作对象的属性

getattr(stu,'name'): 从对象stu中获取name属性

getattr(stu,'函数名'):可获得函数的内存地址

当属性不存在时,报错,如果属性名后面有默认值,就是输出默认值。

class Student():
    def __init__(self, name, age ):
        self.name = name
        self.age = age

    def index(self):
        print('Student.index')

stu = Student('', 20)
res = getattr(stu,'name')
print(res) #
# res1 = getattr(stu,'name1')
# print(res1) # name1属性不存在,会报错 #AttributeError: 'Student' object has no attribute 'name1'
res2 = getattr(stu,'name1',666)
print(res2) # name1不存在,但是后面有默认值。所以不会报错,并且会输出默认值
res3 = getattr(stu,'index')
print(res3) # <bound method Student.index of <__main__.Student object at 0x0000024060610898>>
res3() # Student.index

setattr(stu,‘heigh’,180)  :设置一个不存在的属性,若存在,则为修改操作,不存在则为添加。

class Student():
    def __init__(self, name, age ):
        self.name = name
        self.age = age

    def index(self):
        print('Student.index')

stu = Student('', 20)
print(stu.__dict__) # {'name': '花', 'age': 20}
res=setattr(stu,'height',180)
print(stu.__dict__) # {'name': '花', 'age': 20, 'height': 180}
res1 =setattr(stu,'age',18)
print(stu.__dict__) # {'name': '花', 'age': 18, 'height': 180}

delattr(stu,'age'): 删除

hasattr(stu,'name'): 返回布尔值,判断属性或者方法是否存在

class Student():
    def __init__(self, name, age ):
        self.name = name
        self.age = age

    def index(self):
        print('Student.index')

stu = Student('', 20)
print(stu.__dict__) # {'name': '花', 'age': 20}
res=setattr(stu,'height',180)
print(stu.__dict__) # {'name': '花', 'age': 20, 'height': 180}
res1 =setattr(stu,'age',18)
print(stu.__dict__) # {'name': '花', 'age': 18, 'height': 180}
res2 = delattr(stu,'age')
print(stu.__dict__) #{'name': '花', 'height': 180}
res3 = hasattr(stu,'age')
print(res3) # False
res4 = hasattr(stu,'index')
print(res4) #True

异常

异常:错误发生的信号,我们必须要做处理,否则,后续代码无法正常运行

主动抛出异常 (使用场景:父类限制子类的行为)

  raise 异常的类型

  raise Exception('异常信息')

try:
    被检测的代码
except 异常类型:
    pass
else:
    print() #只有当被检测代码没有异常才会走
finally:
    print() # 不管什么时候都会走
    
 """以上结构是我们为了捕捉代码中出现的异常"""

自己抛出异常

 class Animal():
    # @abc.abstractmethod
    def speak(self):
        raise Exception("请先实现speak方法")

class People(Animal):
    def speak(self):
        pass
    # pass

"""主动抛出异常"""
stu = People()
stu.speak()

 自定义异常

class MyException(BaseException):
    def __init__(self, msg):
        self.msg = msg

    def __str__(self):
        return self.msg


raise MyException("这是异常信息")
posted @ 2023-06-28 18:43  Maverick-Lucky  阅读(22)  评论(0)    收藏  举报