面向对象第四讲

面向对象第四讲

mixins机制

分主类和辅类 继承辅类就有辅类的功能,不影响子类的使用python

命名方式, 以Mixin,able, 为结尾ide

辅类在主类的左边函数

class Vehicle():
    def run(self):
        pass

    def driver(self):  # 驾驶员
        pass


class FlyMixin():
    def fly(self):
        pass


class Car(Vehicle):
    pass


class Automobile(Vehicle):  # 汽车
    pass


class Airplane(FlyMixin, Vehicle):  # 飞机
    pass

"""
如上代码,,汽车,轿车,飞机都有 Vehicle这个类的属性,可是飞机有飞的属性,因此把飞这个属性单独拿出来设置成辅类
"""

内置函数

内置函数就是不用去调用,当知足一些条件后自动执行的代码,内置函数有不少,这里只列举几个经常使用的对象

  1. str继承

    class Student():
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __str__(self):
            print('打印对象的时候会自动触发这个函数的运行,返回值必须是一个字符串')
            return f'{self.name}, {self.age}'
    
    obj = Student('egon', 10)
    print(obj)
    
    ========================================>
    打印对象的时候会自动触发这个函数的运行,返回值必须是一个字符串
    egon, 10
    
    
    """
    __str__这个函数只有在打印对象的时候才会触发,并且返回结果只能是字符串。
    若是没用这个方法,打印对象的结果应该是一个内存地址
    """
    
  2. del递归

    class Student():
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __del__(self):
            print('del is running')
            print('1.手动删除对象时执行 2.应用程序执行完毕时自动触发')
    
    obj = Student('egon', 10)
    del obj
    
    print('end ==================')
    
    ============================================>
    del is running
    1.手动删除对象时执行 2.应用程序执行完毕时自动触发
    end ==================
    
    
    class Student():
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __del__(self):
            print('del is running')
            print('1.手动删除对象时执行 2.应用程序执行完毕时自动触发')
    
    obj = Student('egon', 10)
    
    print('end ==================')
    ==========================================>
    end ==================
    del is running
    1.手动删除对象时执行 2.应用程序执行完毕时自动触发
    
    """
    经过上述两种打印结果得:
    该函数在删除对象时会自动触发
    程序运行结束的时候,也会自动触发这个函数的运行
    """
    
  3. isinstance内存

    class Student():
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    class Course():
        def __init__(self, name):
            self.name = name
    
    
    obj1 = Course('python')
    obj = Student('egon', 10)
    print(isinstance(obj, Student))
    print(isinstance(obj1, Student))
    
    """
    这个内置函数是用来检查,这个对象是否是这个类实例出来的
    """
    
  4. issubclass字符串

    class People():
        pass
    
    class Student(People):
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    class Course():
        def __init__(self, name):
            self.name = name
    
    
    print(issubclass(Student, People))
    print(issubclass(Course, People))
    
    """
    此方法是判断这个类是否是另一个类的子类
    """
    
  5. getattr, setattr,delattrget

    class Foo:
        x=1
        def __init__(self,y):
            self.y=y
    
        def __setattr__(self, key, value):
            print('----> from setattr')
            # self.key=value #这就无限递归了,你好好想一想
            self.__dict__[key]=value #应该使用它
    
    f = Foo(2)
    f.z = 1
    f.x = 111
    print(f.__dict__)
    =====================================>
    ----> from setattr
    ----> from setattr
    ----> from setattr
    {'y': 2, 'z': 1, 'x': 111}
    """
    由上能够得出,这个方法在实例化,增长,修改数据属性的时候会自动触发,
    查看用 self.__dict__[key]=value
    """
    
    class Foo:
        x=1
        def __init__(self,y):
            self.y=y
    
        def __getattr__(self, item):
            print('----> from getattr:你找的属性不存在')
    
    obj = Foo(1)
    obj.m
    """
    当你访问的这个属性不存在的时候会自动触发该方法
    """
    
    class Foo:
        x = 1
    
        def __init__(self, y):
            self.y = y
    
        def __delattr__(self, item):
            print('----> from delattr')
            # del self.item #无限递归了
            self.__dict__.pop(item)     # 这里弹出的是对象属性,不是类属性,由于是对象用__dict__
    
    obj = Foo(111)
    del obj.y
    
    """
    由此能够得出,该方法在执行删除属性的时候会自动触发
    """
    
  6. callit

    class Foo:
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print('__call__ is running')
    
    obj = Foo()
    obj()
    """
    这个方法在对象加括号的时候执行
    """
    

反射

反射就是经过字符串操做类属性或者方法

class Student():
    school = 'sh'
	def __init__(self, name):
		self.name = name
    def func(self):
        print('func is running')


obj = Student('egon')
print(hasattr(obj, 'school'))        # 判断obj对象有没有'school'这个属性,注意这里是字符串
print(getattr(obj, 'school'))        # 拿到对象obj下面的school属性
print(getattr(obj, 's', None))       # 若是obj对象下面有这个属性就拿到,没用会报错,不过能够加第三个参数,没有这个属性的时候会返回第三个参数,通常是None
print(getattr(obj, 'func'))          # 拿到obj下面的func函数属性,拿到的是一个函数的内存地址,加括号能够调用
getattr(obj, 'func')()

setattr(obj, 'school', 123123234)    # 修改obj对象下面school的值
delattr(obj, 'name')                 # 这个是删除对象obj下面的name属性
delattr(Student, 'school')			# 删除Student类下面的school属性


由于python一切皆对象,因此试一下模块是否是也支持这个方法

import time

print(getattr(time, 'time')())

异常

异常就是错误发生的信号,当遇到这个信号就会抛出异常,而且此后的代码不在执行

为何要用异常:
   增长了程序的可靠性,健壮性

语法:
try:
    # 被监测的代码1
    # 被监测的代码1
    # 被监测的代码1
    # 被监测的代码1
    # 被监测的代码1
    pass
except 异常信息1 as e:
    # 捕捉到异常信息
except 异常信息2 as e
# 捕捉到异常信息
except 异常信息3 as e
    # 捕捉到异常信息
except 异常信息4 as e
    pass
except Exception as e:
    pass
else:
    print("当被监测的代码没有异常时候执行")
finally:
    print("无论有没有异常都会执行的")
   

断言

raise

if 1 < 2:
    raise Exception('异常')
    
"""
用这个方法,能够返回返回指定异常,来明确地触发异常, raise后必须是一个异常的类或者是异常的实例,
异常会打印到终端
"""

assert

print(1)
print(2)
assert isinstance(18,int)
assert isinstance(18,str)
print(3)
print(4)

"""
若assert后面的语句成立,则继续执行,负责在此抛出异常
"""

自定义异常

class Myecxeption(BaseException):
    def __init__(self, msg):
        self.msg = msg
    def __str__(self):
        return '异常信息:%s' % self.msg

obj = Myecxeption('自定义的异常')
raise Myecxeption('自定义异常')
# print(obj)

=====================>
__main__.Myecxeption: 异常信息:自定义异常