CSIC_716_20191128【多态、绑定与非绑定方法、isinstance与issubclass 】

多态

what: 同一个事物有不同的形态。

多态的目的:在不知道对象具体类型的情况下,统一对象调用方法的规范。(通俗讲,即规定实现同样功能的方法,一定要起同样的名字)。

多态的表现形式之一就是继承,先抽象再继承。

多态的父类:定制一套统一的规范,子类中重写该方法,并使用这个方法名。

python中不会强制限制子类一定要用父类规定的方法名,所以出现了抽象类。

 

抽象类

what:python中内置了abc模块中有抽象类   import abc

抽象类的作用:让子类必须遵循父类的编写规范。

抽象类不可以被实例化

如何实现抽象类:请看代码

# _*_ coding: gbk _*_
# @Author: Wonder
import abc


class Father(metaclass=abc.ABCMeta):  # 定义时候要加上metaclass = abc.ABCMeta

    @abc.abstractmethod  # 被@abc.abstractmethod装饰的方法,必须在子类中重写,否则会报错。
    def bark(self):
        print('barking......')

    @abc.abstractmethod
    def run(self):
        print('running......')

    def dance(self):
        print('dancing......')

class Sub(Father):
    def poke(self):
        print('poking......')
    def bark(self): # 重写父类方法,不写会报错
        print('sub barking......')
    def run(self):
        print('sub running......')

test = Sub()
test.run()
test.bark()
test.dance()
test.poke()

 注意点:1.父类名后要加上 classmeta = abc.ABCMeta  2.父类方法上要加上@abc.abstractmethod  3.子类务必遵循父类方法的编写规范进行重写,缺一不可。

 

 

鸭子类型

鸭子类型是多态的一种表现形式。

针对不同的对象,根据特点先抽象出相同的方法,再制定一套统一的编写规范

在定义类时,类中的方法都按照统一的规范进行编写。

鸭子类型取消了继承,也取消了抽象类,全凭自觉按照规范编写。这样耦合度就很低。

鸭子类型可以封装出若干个统一的对外的接口,调用相似事物的相同方法,例如:

# _*_ coding: gbk _*_
# @Author: Wonder
class Dog:
    def bark(self):
        print('dog barking')


class Cat:
    def bark(self):
        print('cat barking')


class Bird:
    def bark(self):
        print('bird barking')


def BARK(animal):  # 封装统一对外接口
    animal.bark()


dog = Dog()
cat = Cat()
bird = Bird()

BARK(dog)
BARK(cat)
BARK(bird)

  

总结:

多态的三种表现形式:

>>>继承父类        中度耦合(父类给了规范,但子类可以自由发挥,不用父类的规范)

>>>继承抽象类      高耦合(父类给了规范,并严格限制子类按照规范重写override)

>>>鸭子类型          低耦合(没有继承,类中的方法名 全凭自觉 按照规范编写)

 

 

绑定方法classmethod和非绑定方法staticmethod

classmethod和staticmethod都是pyhton内置的装饰器

classmethod用来标识 类中的某个方法是类的绑定方法。由类来调用,自动传入方法的第一个参数是类。

之前学过类中不加修饰的方法是对象的绑定方法,对象调用这些方法时,会将自身作为第一个参数传入方法,当成self。

 (这一条不知道能否这么总结)  如果对象调用类的绑定方法,第一个传入的值是对象所在的类,子类生成的对象可以调用父类和子类的绑定方法。

# _*_ coding: gbk _*_
# @Author: Wonder
'''
classmethod: 类的绑定方法,只有类可以使用,子类也可以使用。
'''


class Father:
    __key = 'secret'

    def __init__(self, name):
        self.name = name

    @classmethod
    def call(cls, x, y, z):
        return x + y, y + z

    @classmethod
    def info(cls, key):
        if key == 'wonder':
            return cls.__key, cls
        return 'FUCK_NO'


class Sub(Father):
    __key = 1990
    pass


sub_obj = Sub('name')  # 子类实例化一个对象
print(sub_obj.__class__)  #查看对象所属的类为 <class '__main__.Sub'>
res = sub_obj.info('wonder')
print(res)  # ('secret', <class '__main__.Sub'>) 此处需要注意,cls.__key一定找当前类中的,不可以跨类。
print(Father.call(1, 2, 3))  # (3, 5)
print(Sub.call(4, 5, 6))  # (9, 11)
print(Father.info('won'))  # FUCK_NO
print(Sub.info('wonder'))  # ('secret', <class '__main__.Sub'>)

 

 非绑定方法

非绑定方法,相当于在类中定义了一个函数,没有自动传参功能,类和对象都可以使用。

# _*_ coding: gbk _*_
# @Author: Wonder
class Foo:
    @staticmethod
    def rap(name):
        print(f'您的狗名为{name}')

foo_obj = Foo()
foo_obj.rap('阿黄')
Foo.rap('阿黑')

  

 

isinstance 判断一个对象是否是一个类的实例

issubclass 判断一个类是否是另一个类的子类

class A:
    pass


class B(A):
    pass


class C:
    pass


print(isinstance(A(), A))  # True
print(isinstance(B(), A))  # True
print(isinstance(A(), B))  # False
print(isinstance(B(), B))  # True

print(issubclass(C, A))  # False
print(issubclass(B, A))  # True

  

 

补充

uuid模块

import uuid
print(uuid.uuid4())  # a64b11d5-a3f1-46a2-b752-08fc8949457a

uuid.uuid4( )  uuid4是一个纯随机数,与机器无关, 相重的几率很小。通常生成用户id用这个。

posted @ 2019-11-28 15:39  HEU葉孤城  阅读(106)  评论(0编辑  收藏  举报