day30-mixin、重载、多态、绑定与非绑定方法、内置函数

内容回顾

上节课复习
    1、继承
        优点:解决类与类之间代码冗余问题
        缺点:将类耦合到了一起


    2、python支持多继承
        优点:最大程度地重用父类的属性
        缺点:
            1、违背人的思维习惯:继承表达的是一种什么"是"什么的关系
            2、代码可读性会变差
            3、不建议使用多继承,有可能会引发可恶的菱形问题,扩展性变差,
            如果真的涉及到一个子类不可避免地要重用多个父类的属性,应该使用Mixins
        class A(object): # A.mro()
            pass

        class B(A): # B.mro()
            pass

        class C(B) # C.mro()
            pass

        obj=B()
        B.xxx
        obj.xxx

    2、派生:子类中衍生出的新东西
        1、子类独有,父类没有
        2、子类有,父类也有,子类是完全覆盖父类的
        3、子类有,父类也有,子类是在父类的基础上进行拓展


        ps:在子类派生的新方法中如何重用父类的功能
        class A(object):
            def f1(self):
                pass

        class B(A):
            def f1(self):
                A.f1(self)
                拓展的代码


今日内容:
    1、多继承的正确打开方式:mixins机制
    2、在子类派生的新方法中如何重用父类的功能
        方式一:指名道姓调用某一个类下的函数=》不依赖于继承关系
        方式二:super()调用父类提供给自己的方法=》严格依赖继承关系
    3、多态与鸭子类型
    4、绑定方法与非绑定方法
        classmethod
        staticmethod

    5、内置函数

mixin机制

"""
@作者: egon老湿
@微信:18611453110
@专栏: https://zhuanlan.zhihu.com/c_1189883314197168128
"""

# 多继承的正确打开方式:mixins机制
# mixins机制核心:就是在多继承背景下尽可能地提升多继承的可读性
# ps:让多继承满足人的思维习惯=》什么"是"什么
class Vehicle:
    pass

class FlyableMixin:
    def fly(self):
        pass

class CivilAircraft(FlyableMixin,Vehicle):  # 民航飞机
    pass

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

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


import socketserver
# 补充:通常Mixin结果的类放在左边

在子类派生的新方法中如何重用父类的功能

在子类派生的新方法中如何重用父类的功能
方式一:指名道姓调用某一个类下的函数 =》不依赖于继承关系


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

    def f1(self):
        print('%s say hello' % self.name)


class Teacher(OldboyPeople):
    def __init__(self, name, age, sex, level, salary):
        OldboyPeople.__init__(self, name, age, sex)

        self.level = level
        self.salary = salary


tea_obj = Teacher('egon', 18, 'male', 10, 3000)
print(tea_obj.__dict__)

方式二:super()调用父类提供给自己的方法 =》严格依赖继承关系
调用super()会得到一个特殊的对象,该对象会参照发起属性查找的那个类的mro, 去当前类的父类中找属性


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

    def f1(self):
        print('%s say hello' % self.name)


class Teacher(OldboyPeople):
    def __init__(self, name, age, sex, level, salary):
        # super(Teacher,self).__init__(name,age,sex)
        super().__init__(name, age, sex)  # 调用的是方法,自动传入对象

        self.level = level
        self.salary = salary


# print(Teacher.mro())
tea_obj = Teacher('egon', 18, 'male', 10, 3000)
print(tea_obj.__dict__)


super()案例


class A:
    def test(self):
        print('from A')
        super().test()


class B:
    def test(self):
        print('from B')


class C(A, B):
    pass


obj = C()
obj.test()

print(C.mro())


class A:
    def test(self):
        print('from A')
        super().test1()


class B:
    def test(self):
        print('from B')


class C(A, B):
    def test1(self):
        print('from C')


obj = C()
obj.test()

print(C.mro())

多态

1、什么多态:同一事物有多种形态


class Animal:
    pass


class People(Animal):
    pass


class Dog(Animal):
    pass


class Pig(Animal):
    pass


2、为何要有多态 =》多态会带来什么样的特性,多态性
多态性指的是可以在不考虑对象具体类型的情况下而直接使用对象


class Animal:  # 统一所有子类的方法
    def say(self):
        print('动物基本的发声频率。。。', end=' ')


class People(Animal):
    def say(self):
        super().say()
        print('嘤嘤嘤嘤嘤嘤嘤')


class Dog(Animal):
    def say(self):
        super().say()
        print('汪汪汪')


class Pig(Animal):
    def say(self):
        super().say()
        print('哼哼哼')


obj1 = People()
obj2 = Dog()
obj3 = Pig()


obj1.say()
obj2.say()
obj3.say()

定义统一的接口,接收传入的动物对象


def animal_say(animal):
    animal.say()


animal_say(obj1)
animal_say(obj2)
animal_say(obj3)


print('hello'.__len__())
print([1, 2, 3].__len__())
print({'a': 1, 'b': 2}.__len__())


def my_len(val):
    return val.__len__()


print(my_len('hello'))
print(my_len([1, 2, 3]))
print(my_len({'a': 1, 'b': 2}))

len('hello')
len([1, 2, 3])
len({'a': 1, 'b': 2})


python推崇的是鸭子类型


class Cpu:
    def read(self):
        print('cpu read')

    def write(self):
        print('cpu write')


class Mem:
    def read(self):
        print('mem read')

    def write(self):
        print('mem write')


class Txt:
    def read(self):
        print('txt read')

    def write(self):
        print('txt write')


obj1 = Cpu()
obj2 = Mem()
obj3 = Txt()

obj1.read()
obj1.write()

obj2.read()
obj2.write()

obj3.read()
obj3.write()


了解:


class Animal(metaclass=abc.ABCMeta):  # 统一所有子类的标准
    @abc.abstractmethod
    def say(self):
        pass

# obj=Animal() # 不能实例化抽象类自己


class People(Animal):
    def say(self):
        pass


class Dog(Animal):
    def say(self):
        pass


class Pig(Animal):
    def say(self):
        pass


obj1 = People()
obj2 = Dog()
obj3 = Pig()

绑定方法和非绑定方法

一:绑定方法:特殊之处在于将调用者本身当做第一个参数自动传入
1、绑定给对象的方法:调用者是对象,自动传入的是对象
2、绑定给类的方法:调用者类,自动传入的是类


class Mysql:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

    def func(self):
        print('%s:%s' % (self.ip, self.port))

    @classmethod  # 将下面的函数装饰成绑定给类的方法
    def from_conf(cls):
        print(cls)
        return cls(settings.IP, settings.PORT)

# obj1=Mysql('1.1.1.1',3306)


obj2 = Mysql.from_conf()
print(obj2.__dict__)

二:非绑定方法 -》静态方法:
没有绑定给任何人:调用者可以是类、对象,没有自动传参的效果


class Mysql:
    def __init__(self, ip, port):
        self.nid = self.create_id()
        self.ip = ip
        self.port = port

    @staticmethod  # 将下述函数装饰成一个静态方法
    def create_id():
        import uuid
        return uuid.uuid4()

    @classmethod
    def f1(cls):
        pass

    def f2(self):
        pass


obj1 = Mysql('1.1.1.1', 3306)

print(Mysql.create_id)
print(obj1.create_id)

Mysql.create_id(1, 2, 3)
obj1.create_id(4, 5, 6)

print(Mysql.create_id)
print(Mysql.f1)
print(obj1.f2)

内置函数

print(abs(-1))
print(all([1, 'aaa', '1']))
print(all([]))

print(any([0, None, 1]))
print(any([]))

print(bin(11))
print(oct(11))
print(hex(11))

print(bool(''))


def func():
    pass


class Foo:
    pass


print(callable(Foo))  # 方

print(chr(65))
print(ord('A'))

不可变集合
s = frozenset({1, 2, 3})

hash(不可变类型)

print(round(1.5))
print(round(1.4))


10 ** 2 % 3
print(pow(10, 2, 3))
s = slice(1, 4, 2)
l1 = ['a', 'b', 'c', 'd', 'e']
l2 = ['aaa', 'bbb', 'ccc', 'ddd', 444]

print(l1[1:4:2])  # l1[s]
print(l2[1:4:2])  # l2[s]


== == == == == == == == =》掌握
v1 = 'hello'
v2 = [111, 222, 333, 444, 5555, 6666]
res = zip(v1, v2)
print(list(res))

== == == == == == == == =》掌握
print(divmod(10000, 33))

== == == == == == == == =》掌握


class Foo:
    pass


obj = Foo()
obj.xxx = 1111
print(dir(obj))  # obj.哪些属性

== == == == == == == == =》掌握
for i, v in enumerate(['a', 'b', 'c']):
    print(i, v)

== == == == == == == == =》掌握
res = eval('{"a":1}')  # 执行字符串中的表达式
print(res, type(res))


== == == == == == == == =》掌握


class Foo:
    pass


obj = Foo()
print(isinstance(obj, Foo))
print(isinstance([], list))  # 类型判断推荐使用isinstance
print(type([]) is list)  # 不推荐使用

== == == == == == == == =》掌握
time = __import__('time')
time.sleep(3)

下个周:反射
setattr
getattr
delattr
hasattr

作业

本周作业:综合应用面向对象

角色:学校、学员、课程、讲师
要求:
1. 创建北京、上海 2 所学校
2. 创建linux , python , go 3个课程 , linuxpy 在北京开, go 在上海开
3. 课程包含,周期,价格,通过学校创建课程
4. 通过学校创建班级, 班级关联课程、讲师
5. 创建学员时,选择学校,关联班级
5. 创建讲师角色时要关联学校,
6. 提供两个角色接口
6.1 学员视图, 可以注册, 交学费, 选择班级,
6.2 讲师视图, 讲师可管理自己的班级, 上课时选择班级, 查看班级学员列表 , 修改所管理的学员的成绩
6.3 管理视图,创建讲师, 创建班级,创建课程

7. 上面的操作产生的数据都通过pickle序列化保存到文件里
原文地址:https://www.cnblogs.com/zdw20191029/p/14553340.html