组合,mixins机制,面向对象中内置函数,反射,异常

时间:2021-08-26
本文章向大家介绍组合,mixins机制,面向对象中内置函数,反射,异常 ,主要包括组合,mixins机制,面向对象中内置函数,反射,异常 使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

昨日内容回顾(面向对象的三大特征)

继承

# 继承解决了类与类之间的代码冗余问题

# 语法
class Parent1:
    pass

class Parent2:
    pass

class Sub1(Parent1):
    pass

class Sub2(Parent1, Parent2):
    pass

# 父类,用来让子类继承

class People():
    school = 'SH'
	def __init__(self, name, age, gender):
         self.name = name
         self.age = age
         self.gender = gender

class Student(People):
    def __init__(self, name, age, gender, course=None):
		if course is None:
             course = []
         self.courses = course
         # People.__init__(self, name, age, gender)   # __init__变成了普通方法
       	 # super(Student, self).__init__(name, age, gender) # python2
         # super().__init__(name, age, gender) # python3
            super也遵循mro列表

 class Teacher():
      def __init__(self, name, age, gender, level):
            self.name = name
            self.age = age
            self.gender = gender
            self.level = level

单继承下的属性查找

class Foo:
    def f1(self):
        print('from foo')

    def f2(self):
        self.f1()

class Bar(Foo):
    def f1(self):
        print('from bar')

# 属性查找顺序:先从对象自己本身找,然后去产生对象的类中找,再去继承的父类中找
obj = Bar()
obj.f2()

运行结果:from bar

###############################隐藏属性######################################

class Foo:
    def __f1(self):      # self._Foo__f1()
        print('from foo')

    def f2(self):
        self.__f1()      # self._Foo__f1()

class Bar(Foo):
    def __f1(self):      # self._Bar__f1()
        print('from bar')

# 属性查找顺序:先从对象自己本省去找,然后去产生对象的类中取找,在取继承的父类中去找
obj = Bar()
obj.f2()

运行结果:from foo

多继承下的属性查找

# 经典类 : 在python2中存在的,
# 新式类  : 在python3中全部是新式类,默认继承object类

############菱形查找###################
# 经典类中多继承属性查找顺序:深度优先查询(图1)
# 新式类中多继承属性查找顺序:广度优先查询(图2)

图1**

图2**

super和mro

# 严格按照mro列表去找

多态和多态性

# 同一种事物的多种形态

"""
	多态类中的继承,是限制子类中的行为
"""
# #############################抽象类(不推荐)###########################

import abc  # abstract
# 继承 metaclass=abc.ABCMeta 之后, 类已经成为了抽象类
# **抽象类的特点:只能被继承,不能被实例化**
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def speak():pass

class People(Animal):
    pass

obj = People()
obj.speak()

#############################鸭子类型###########################

class People():
    def jiao(self):
        pass

class Pig():
    def jiao(self):
        pass

class Dog():
  	def jiao(self):
         pass

obj = People()
def animal(animal):
    return animal.jiao()

animal(obj)

# 多态带来的特性:在不考虑数据类型的情况下,直接调用对应的方法

len()

# python3中统一了类与类型的概念
print()

今日内容详细

  • 组合
  • mixins机制(了解)
  • 面向对象中内置函数(魔术方法,简称魔法, 以__开头的方法)
  • 反射,掌握4个方法即可
  • 异常

组合

# 解决类与类之间代码冗余问题:
	1. 继承
    2. 组合

组合:一个对象拥有一个属性, 属性的值必须是另外一个对象
继承满足的是:什么是什么的关系  # is-a
组合满足的是:什么有什么的关系  # has-a
class Foo:
    def __init__(self, m):
        self.m = m

class Bar():
    def __init__(self, n):
        self.n = n
obj=bar(1)
obj2=Foo(2)
# obj就是一个超级对象
obj.x=obj2
print(obj.x.m)

# 运行结果:2

分步

class Foo:
    def __init__(self, m):
        self.m = m

class Bar():
    def __init__(self, n):
        self.n = n

obj = Foo(10)
print(obj.m)            # 10

obj1 = Bar(20)
print(obj1.n)           # 20

****************************************************************

class Foo:
    def __init__(self, m):
        self.m = m

class Bar():
    def __init__(self, n):
        self.n = n

obj = Foo(10)
print(obj.m)

obj1 = Bar(20)
# print(obj1.n) 
obj.x=obj1         
print(obj.x.n)   # obj.x <————> obj1.n

组合:一个对象拥有一个属性, 属性的值必须是另外一个对象

案例

class People():
    school = 'SH'

    def __init__(self, name, age, gender, course=None):
        if course is None:
            course = []
        self.name = name
        self.age = age
        self.gender = gender
        self.courses = course

class Course():
    def __init__(self, course_name, course_period, course_price):
        self.course_name = course_name
        self.course_period = course_period
        self.course_price = course_price

python = Course('python', '5mon', 1000)
linux = Course('linux', '6mon', 2000)
print(python.course_name)
print(python.course_period)
print(python.course_price)

print(linux.course_name)
print(linux.course_period)
print(linux.course_price)

class Student(People):
    school = 'SH'

    def __init__(self, name, age, gender, course_name, course_period, course_price, course=None):
        if course is None:
            course = []
        self.courses = course
        super().__init__(name, age, gender)

    def choose_course(self, course):
        self.courses.append(course)
        print("%s选课成功%s" % (self.name, self.courses))

stu = Student('egon', 18, 'male', 'python', '6mon', 1000)

stu.courses.append(python)
stu.courses.append(linux)
for i in stu.courses:
    print(i.course_name)

class Teacher(People):
    school = 'SH'

    def __init__(self, name, age, gender, level=None):
        self.level = level
        super().__init__(name, age, gender)

    def score(self, stu_obj, score):
        stu_obj.score = score
        print("%s给%s打%s分" % (self.name, stu_obj.name, score))

tea = Teacher('egon', 18, 'male')
tea.course = python       # 组合:一个对象拥有一个属性, 属性的值必须是另外一个对象

print(tea.course.course_name)

mixins机制

1. 分主类和辅类
2. 命名方式一般以 Mixin, able, ible 为后缀
3. 辅类位置一般在主类的左边

Mixins是从多个类中重用代码的好方法,但是需要付出相应的代价,我们定义的Minx类越多,子类的代码可读性就会越差
class Vehicle:  # 交通工具
     def run(self):
         pass
     def run1(self):
         pass
     def run2(self):
         pass
     def run3(self):
         pass

class FlyMixin():
# class Flyable():
    def fly(self):
        '''
        飞行功能相应的代码
        '''
        print("I am flying")

class CivilAircraft(FlyMixin, Vehicle):  # 民航飞机 #辅类里面有一些功能可有可无,继承则有
    pass

class Helicopter(FlyMixin, Vehicle):  # 直升飞机
    pass

class Car(Vehicle):  # 汽车并不会飞,但按照上述继承关系,汽车也能飞了
    pass

# import socketserver

内置函数

# __init__()
# __str__()  ********
class Student():
    school = 'SH'
stu = Student()
print(stu)

运行结果:<__main__.Student object at 0x00000222CEBB4C70> 默认返回的是对象的内存地址
**__str__方法 #重要**
1. 打印对象会自定触发的函数,方法
2. 返回值必须是字符串类型

class Student():
    school = 'SH'

    def __str__(self):
        return self.school

stu = Student()
print(stu)

运行结果:SH
**__del__方法**

class Student():
    school = 'SH'

    def __init__(self):
        self.f = open('xxx', mode='w')

    # 1. 删除对象属性的时候,自动触发
    # 2. 当所有代码执行完成之后,还会自动触发
    def __del__(self):
        print("__del__")
        self.f.close()

stu = Student()

# stu.x = 1
# del  stu.x

print("end=====>")

##########__del__################
补充:
a = 123 # int(123)

s = str('abc')
print(type(s) is str)
print(isinstance(s, int))

class Foo:
    pass

print(issubclass(Foo, object))

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')
        print(key)
        print(value)
        self.key = value  # 这就无限递归了,你好好想想
        self.__dict__[key] = value  # 应该使用它

    def __delattr__(self, item):
        print('----> from delattr')
        del self.item #无限递归了
        self.__dict__.pop(item)

obj = Foo(10)

obj.z = 10
**必须掌握__call__方法**

class Foo:

    def __init__(self):
        pass
    # 当给对象加括号时候,自定触发的函数
    def __call__(self, *args, **kwargs):
        print('__call__')

obj = Foo()  # 执行 __init__
obj()

obj.x = 1
obj.'x' = 1

反射

# 通过字符串操作属性

# getattr()
# hasattr()
# setattr()
# delattr()
class Foo:
    school = 'SH'

obj = Foo()

x = input(":>>").strip()  # school => str

print(obj.x)
print(obj.'school')

反射:掌握反射中的四个方法即可
1.
print(getattr(obj, x))
print(getattr(obj, 'school'))
print(getattr(obj, 'school1', 'SH'))
print(getattr(obj, 'school', 'SH111'))

2. 字符串形式设置属性
setattr(obj, 'y', 10)
print(obj.__dict__)

3.
delattr(Foo, 'school')
print(Foo.__dict__)

4. 如何判断是否有这个属性
print(hasattr(obj,'school'))
#################################超级重要#############################
class Foo:
    school = 'SH'

    def func(self):
        print("func")

obj = Foo()

getattr(obj, 'func')()
# print(getattr(obj, 'func'))

hander = getattr(obj, 'func', None)

def test(*args, **kwargs):
    return hander(*args, **kwargs)

test()

import time
# time.sleep(3)

getattr(time, 'sleep')(3)

import time

time = __import__('time')
time.sleep(3)

异常

# 什么是异常?
	异常就是错误发生额的信号, 如果不对该信息进行处理, 那么, 之后的代码就不会运行

    具体来说:
    	1. 语法错误
        	# SyntaxError:
            print(123
        2. 逻辑错误
                 # 有些逻辑错误可以尽量写到完美
                 NameError: name 'x' is not defined
                  print(x)

# 为什么用异常?
      为了增强代码的健壮性

# 怎么用异常?
      try:
         	被监测的代码1
             被监测的代码2
             被监测的代码3
             被监测的代码4
             被监测的代码5
	except 异常错误1 as e:
    	pass
	except 异常错误2 as e:
    	pass
	except 异常错误3 as e:
   		 pass
	else:
    	print("当被检测的代码没有异常的时候触发")
	finally:
    	print("不管有咩有异常,都会走")
print(123)

x = 1
print(x)

a = [1, 2, 3]

if len(a) >= 2:
    a[2]
else:
    print("错误")

try:
    x = 1
except IndexError as e:
    pass
except IndexError as e:
    pass
except IndexError as e:
    pass
else:
    print("123")
finally:
    print("123")

NameError
print(x)

IndexError
a = [1, 2]
a[3]

AttributeError
class Foo:
    pass
obj = Foo()

obj.x

TypeError
for i in 123:
    pass

ZeroDivisionError
1/0

try:
    a = [1, 2, 3]
    # print(a)
    # a[5]
    1/0
except IndexError as e:
    print(e)
except AttributeError as e:
    print(e)
except ZeroDivisionError as e:
    print(e)

else:
    print("这是else")
finally:
    print("这是finally")

try:
    pass
except:
    pass

try:
    pass
else:
    pass

try:
    pass

finally:
    pass

try:
    pass
except:
    pass
else:
    pass

a = [1, 2, 3]

if len(a) >= 5:
    print(123)
else:
    # print("索引错误")
    # return
    # break
    raise Exception("索引错误")

assert len(a) == 5

print("end----")

class Animal():
    def speak(self):
        raise Exception("必须实现speak方法")

class People(Animal):
    pass

obj = People()

obj.speak()

自定义异常类
class MyException(BaseException):
    def __init__(self, msg):
        self.msg = msg

    def __str__(self):
        return self.msg

raise MyException("这是自定义异常类")

原文地址:https://www.cnblogs.com/echoxkx/p/15191822.html