1 2 3 4

多态 抽象类 鸭子类型 classmethod 和 staticmethod isinstance 和 issubclass 反射

1.多态

1.什么是多态?

​ -多态指的同一种类型的事物的不同形态。

2.多态的目的:

​ -'多态'也成为'多态性',目的是为了再不知道对象的具体类型情况下,统一对象的调用方法的规范(比如写字)

​ -多态的表现形式之一就是 继承

​ -先抽象,在继承

​ 父类:定制一套统一的规范,(比如:方法统一)

​ 子类:遵循父类的统一的规范。(比如子类遵循父类方法名统一的)

​ 注意:在python中不会强制限制子类的必须要遵循父类的规范,所以出现了抽象类。

#动物类
class Animal:######这个就是统一的规范
    #方法吃
    def eat(self):
        pass
    #方法 叫
    def speak(self):
        pass

    #猪类
class Pig(Animal):
    def eat(self):####这个就是根据父类的规范来操作的
        print('baiji...')

    def speak(self):
        print('哼哼哼...')

#猫
class Cat(Animal):
    def eat(self):
        print('yaojiyaoji')

    def speak(self):
        print('喵喵...')

#狗类
class Dog(Animal):
    def eat(self):
        print('tianjitianji')

    def speak(self):
        print('汪汪...')

animal1 = Dog()
animal2 = Cat()
animal3 = Pig()
animal1.eat()

下面这个是一个反面的教材,这个就是个错误的

class Animal:######这个就是统一的规范
    #方法吃
    def eat(self):
        pass
    #方法 叫
    def speak(self):
        pass

    #猪类
class Pig(Animal):
    def eat(self):
        print('baiji...')

    def speak(self):
        print('哼哼哼...')

#猫
class Cat(Animal):
    def chi(self):######和父类的规范要求不一样
        print('yaojiyaoji')

    def tell(self):
        print('喵喵...')

#狗类
class Dog(Animal):
    def chi_1(self):######和父类的规范要求不一样
        print('tianjitianji')

    def jiao(self):
        print('汪汪...')

2.抽象类

1.什么是抽象类?

​ -在python中内置的abc模块中,有一个抽象类

2.抽象类的作用

​ -让子类必须遵循父类的编写规范

3.如何实现抽象化

​ -父类需要继承abc模块中,metaclass,abc.ABCMeta

​ -在父类的方法中,需要装饰上abc.abstractmethod

注意:在python中不推荐使用抽象类。

注意:子类必须按照父类的方法编写规范,缺一不可,父类中有几个抽象的抽象方法,子类就必须要定义几个。

父类中的有的 子类中一定要有几个,子类中可以派生出自己的其他的

import abc
#父类
class Animal(metaclass = abc.ABCMeta):
    @abc.abstractmethod
    def eat(self):###方法吃
        pass
	@abc.abstractmethod
    def speak(self):
        pass

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

    def eat(self):
        print('biajiji')

    def speak(self):
        print('哼哼...')

print(Pig.__dict__)
print(Animal.__dict__)
pig_obj = Pig()

3.鸭子类型

1.什么是鸭子类型?

​ -不同的对象,只要长的像鸭子,动作行为像鸭子,那他就是鸭子

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

2.为什么有鸭子类型?

​ -不同的对象,先抽象出相同类型的方法,给他们制定一套统一的规范。

​ -所有的类,在定义时都按照统一的规范进行编写

​ -在定义之前,先定义一套鸭子类型规范

3.多态的三种表现形式:

​ 1.继承父类

​ -耦合度高,程序的可扩展性低

​ 2.继承抽象类

​ -耦合度极高,程序的可扩展性极低

​ 3.鸭子类型‘

​ -耦合度低,程序的可扩展性高

注意:在python中,强烈推荐鸭子类型

#猪类
class Pig:
    def eat(self):
        print('biajiji')

    def speak(self):
        print('哼哼...')

#猫类
class Cat:
    def eat(self):
        print('yaojiyaoji...')

    def speak(self):
        print('miaomiao...')

#狗类
class Dog:
    def eat(self):
        print('tianjitianji...')

    def speak(self):
        print('汪汪...')
    - 鸭子类型规范::
            - eat_fish:
            - swimming:

        - class Duck1:####这个就是鸭子类型 
            def eat_fish(self):
                pass

            def swimming(self):
                pass

        - class HCY:
            def eat_fish(self):
                pass

            def swimming(self):
                pass

以上的是鸭子类型,这个类型跟继承父类,比没有父类的规范要求

跟抽象类的比,没有父类的导入模块的要求

多态的炫技
#猪类
class Pig:
    def eat(self):
        print('biajiji...')

    def speak(self):
        print('hengheng...')

#猫类
class Cat:
    def eat(self):
        print('hengheng...')

    def speak(self):
        print('miaomiao...')

#狗类
class Dog:
    def eat(self):
        print('tianjitianji')

    def speak(self):
        print('wangwang...')

dog = Dog()
pig = Pig()
cat = Cat()
#多态之炫技
def SPEAK(animal):
    animal.speak()

SPEAK(dog)
SPEAK(cat)
>>>>>>>>>>>>>>>>>
wangwang...
miaomiao...


str1 = 'tank is very handsome!'
def Len(obj):
    return obj.__len__()
print(Len(str1))###具体的一个字符串是一个对象,对象自己的内置方法

print(len(str1))
>>>>>>>>>>>>>>>>>
22
22

4.classmethod 和staticmethod

-都是python解释器内置的装饰器

classmethod:

​ -是一个装饰器,给在类内部定义方法中装饰,将类内部方法变为“类的绑定方法”

staticmethod

​ -翻译:静态方法

​ -是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为“非绑定方法”

对象的绑定方法:

​ -由对象来调用,由谁来调用,会将对象当作第一个参数传入;

类的绑定方法:

​ -由类来调用,由谁来调用,会将类作为第一个参数来传入;

非绑定方法:

​ -可以由对象或者类来调用,谁来调用都是一个普通方法(普通函数),方法需要接收几个参数,就传入几个。

1.classmethod

#校验查看隐私的信息
class DB:
    __data = 'tank is very handsome!'
    def __init__(self,user,pwd,role):
        self.user = user
        self.pwd = pwd
        self.role = role


    def check_db(self):

        if self.user == 'tank' and self.pwd == '123' and self.role == 'admin':
            print('检验通过')
            print(self.__class__.__data)
            return self.__class__.__data
##__class__ 查看当前对象的类

db_obj = DB('tank','123','admin')
db_obj.check_db()
>>>>>>>>>>>>>>>>>>>
检验通过
tank is very handsome!
class DB:
    __data = 'tank is very handsome!'
    def __init__(self,user,pwd,role):
        self.user = user
        self.pwd = pwd
        self.role = role
    # @classmethod
    #在类的内部要调用产生一个实例,———>对象
    # def init(cls,user,pwd,role): ##cls 指的是类
    #     return cls(user,pwd,role)

    @classmethod
    def check_db(cls,user,pwd,role):
        obj = cls(user,pwd,role)#这个是类的实例化产生一个对象

    #查看数据前,必须通过校验
        if obj.user == 'tank'and obj.pwd == '123'and obj.role == 'admin':
            print('校验通过')
            print(cls.__data)
            return cls.__data

DB.check_db('tank','123','admin')
>>>>>>>>>>>>>>>>>
校验通过
tank is very handsome!

import uuid :用于产生随机字符串的模块

​ -具体是由时间戳及某种算法组合而成,会产生一串世界上独一无二字符串

​ -print(uuid.uuid4()) #####产生的是一串字符串

2.staticmethod

class Foo:

    @staticmethod #####变成一种非绑定的方法
    def func(res):
        print(res)

obj = Foo()
#对象调用非绑定方法
obj.func(123)
###结果是123
Foo.func(1234)
>>>>>>>>
1234


如果没有@staticmethod
class Foo:

   
    def func(res):
        print(res)
        
 Foo.func(1234)#####类调用的就是一个普通的函数 res需要一个实参
>>>>>>>>>>>>>
1234

class Foo:

     
    def func(self,res):
        print(res)

obj = Foo()
#对象调用非绑定方法
obj.func(123)   ####对象的调用的是把自身作为第一个值传入,需要2个参数self,res
>>>>>>>>>>>>
123

5.isinstance issubclass

-这两个都是python的内置模块

-isinstance :判断一个对象是否是另一个类的实例。

​ -如果是:True

​ -如果不是:False

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

​ -如果是:True

​ -如果不是:False

class Foo:
    pass

class Goo:
    pass
goo_obj = Goo()

foo_obj = Foo()
print(isinstance(foo_obj,Foo))
print(isinstance(goo_obj,Foo))
>>>>>>>>>>>>>>>>
True
False
class Foo:
    pass
class Goo(Foo):
    pass
class Hoo:
    pass

print(issubclass(Goo,Foo))
print(issubclass(Hoo,Foo))
>>>>>>>>>>>>>>>
True
False

6.反射

-反射指的是通过’字符串''对对象的属性进行操作

​ -hasattr :通过'字符串'判断对象的属性或方法是否存在

​ -getattr:通过'字符串'获取对象的属性或者方法

​ -setattr:通过'字符串'设置对象的属性或方法

​ -delattr: 通过'字符串'删除对象的属性或者方法

注意:反射的4个方法是python的内置的

###hasattr
class Foo:
    def __init__(self,x,y):
        self.x = x
        self.y = y
foo_obj = Foo(10,20)
#hasattr
print(hasattr(foo_obj,'x'))
print(hasattr(foo_obj,'y'))
print(hasattr(foo_obj,'z'))
>>>>>>>>>>>>>>>>>>>>>>>
True
True
False

###getattr
class Foo:
    def __init__(self,x,y):
        self.x = x
        self.y = y
foo_obj = Foo(10,20)

res = getattr(foo_obj,'x')
print(res)
res1 = getattr(foo_obj,'z','默认值')###z不存在,可以在后面加一个默认值,字符串类型的
print(res1)
>>>>>>>>>>>>>>
10
123

####setattr
class Foo:
    def __init__(self,x,y):
        self.x = x
        self.y = y
foo_obj = Foo(10,20)
setattr(foo_obj,'z',30)  #这个setattr的有过这个字符串有值 再设置就会更新,如果是没有值的  会新创建一个属性
print(hasattr(foo_obj,'z'))
>>>>>>>>>>>>>>>>>>>>>>
True

###delattr
class Foo:
    def __init__(self,x,y):
        self.x = x
        self.y = y
foo_obj = Foo(10,20)
delattr(foo_obj,'x')
print(hasattr(foo_obj,'x'))
>>>>>>>>>>>>>>
False



##反射的应用
#反射的应用
class FileControl:
    def run(self):
        while True:
            user_input = input('请输入upload 或者download:').strip()
            if hasattr(self,user_input):
                func = getattr(self,user_input)
                func()
                break
            else:
                print('输入有误')

    def upload(self):
        print('文件正在上传...')

    def download(self):
        print('文件正在下载...')
filecontrol_obj = FileControl()
filecontrol_obj.run()
>>>>>>>>>>>>>>>>>>
请输入upload 或者download:sffjf
输入有误
请输入upload 或者download:dfgf
输入有误
请输入upload 或者download:a1223
输入有误
请输入upload 或者download:download
文件正在下载...
Process finished with exit code 0
posted @ 2019-11-29 15:41  ^更上一层楼$  阅读(121)  评论(0编辑  收藏  举报