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

多态

多态指的是同一种类型的事物,不同的形态

多态的目的:

多态也称之为多态性,目的是为了在不知道对象具体类型的情况下,统一对象调用方法的规范(例如名字)

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

先抽象,再继承

父类:定制一套统一的规范 如方法名统一

子类:遵循父类的统一的规范 如子类遵循父类方法名的统一

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

class Father:
    def func1(self):
        pass
    def speak(self);
    	pass
class Sub1(Father):
    def func1(self):
        pass
    def speak(self):
        pass
class Sub2(Father):
    def func1(self):
        pass
    def speak(self):
        pass

抽象类

什么是抽象类:

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

抽象类的作用:

让子类必须遵守父类的编写规范

如何实现抽象类:

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

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

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

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

import abc
错误示范

# 父类
class Father(metaclass=abc.ABCMeta):

    # 方法吃
    @abc.abstractmethod
    def eat(self):
        pass

    # 方法叫
    @abc.abstractmethod
    def speak(self):
        pass


class Sub(Father):
    def eat(self):
        pass

    def drink(self):
        print(1)


sub_obj = Sub()
sub_obj.eat()
执行就会报错
父类中有几个抽象方法,子类就必须要定义几个

正确示范
# 父类
class Father(metaclass=abc.ABCMeta):

    # 方法吃
    @abc.abstractmethod
    def eat(self):
        pass

    # 方法叫
    @abc.abstractmethod
    def speak(self):
        pass


class Sub(Father):
    def eat(self):
        pass

    def speak(self):
        print(1)
	
    def drink(self):
        pass

鸭子类型

什么是鸭子类型:

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

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

为什么要有鸭子类型:

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

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

多态的三种表现形式:

继承父类:

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

继承抽象类:

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

鸭子类型:

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

注意:在python中强列推荐使用鸭子类型

classmethod与staticmethd

classmethod与staticmethod都是python解释器内置的装饰器

classmethod:

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

staticmethod:

静态方法

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

回顾:

对象的绑定方法:

由对象来调用,由谁来调用,会将谁作为第一个参数传入。

类的绑定方法:

由类来调用,由谁来调用,会将谁当作第一个参数传入

非绑定方法:

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

注意:__ class __: 是用来查看当前对象的类

import uuid 用来产生随机字符串的模块,由时间戳以及某种算法结合而成,会产生一串世界上独一无二的字符串

print(uuid.uuid4())

classmethod_Demo:
class DB:
    __data = 'nothing can not be done!'

    def __init__(self, user, pwd, role):
        self.user = user
        self.pwd = pwd
        self.role = role

    # cls指的是类
    @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(obj.__data)


DB.check_db('tank', '123', 'admin')

user_info = {
    'user': None
}


class User:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex
        self.__uid = uuid.uuid4()

    def register(self, user, pwd):
        self.user = user
        self.pwd = pwd

        with open('user.txt', 'w', encoding='utf-8') as f:
            f.write(
                f'{self.name},{self.age},{self.sex},{self.user},{self.pwd}'
            )

    def login(self, user, pwd):
        if self.user == user and self.pwd == pwd:
            print('通过登录!')
            user_info['user'] = user
        else:
            print('用户名或密码错误!')


user_obj = User('tank', 17, 'male')
user_obj.register('tank_jam', '123')
user_obj.login('tank_jam', '123')


通过登录!

isinstance与issubclass是python的内置模块

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

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

​ 如果是:True

​ 如果不是:False

# isinstance:
class Foo:
    pass

class Boo:
    pass

foo_obj = Foo()
boo_obj = Boo()

print(isinstance(foo_obj, Foo))  # True
print(isinstance(boo_obj, Foo))  # False


# issubclass
class Father:
    pass


class Sub(Father):
    pass


class Foo:
    pass


print(issubclass(Sub, Father))  # True
print(issubclass(Foo, Father))  # False

反射:

​ 反射指的是通过“字符串”对对象的属性进行操作

​ -hasattr: 通过“字符串”判断对象的属性或方法是否存在 hasattr(self, str)

​ -getattr: 通过“字符串”获取对象的属性或方法 getattr(self, str, 默认值)

​ -setattr:通过“字符串”设置对象的属性或方法 seet(self, str, 属性值)

​ -delattr:通过“字符串”删除对象的属性或方法 delattr(self, str)

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

class Foo:
    def __init__(self, x, y):
        self.x = x
        self.y = y


foo_obj = Foo(10, 20)
print(hasattr(foo_obj, 'x'))
print(hasattr(foo_obj, 'z'))

print('=========================')

print(getattr(foo_obj, 'x'))
print(getattr(foo_obj, 'z'))

结果:
True
False
=========================
10
Traceback (most recent call last):
  File "F:/python_work/python_oldboyedu_learn/day23/反射.py", line 14, in <module>
    print(getattr(foo_obj, 'z'))
AttributeError: 'Foo' object has no attribute 'z'
    
    
setattr(foo_obj, 'z', 100)
print(hasattr(foo_obj, 'z'))

print('===================')

delattr(foo_obj, 'z')
print(hasattr(foo_obj, 'z'))


结果:
True
===================
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('文件正在下载中。。。')


file_control_obj = FileControl()
file_control_obj.run()


结果:
请输入 上传 upload 或 下载 download:as
输入有误!
请输入 上传 upload 或 下载 download:upload
文件正在上传。。。


posted @ 2019-11-28 16:13  godlover  阅读(108)  评论(0编辑  收藏  举报