首页 > 编程语言 > 详细

python基础语法17 面向对象3 多态,抽象类,鸭子类型,classmethod与staticmethod,isinstance与issubclass,反射

时间:2019-11-28 20:16:03      阅读:82      评论:0      收藏:0      [点我收藏+]

多态

1.什么是多态?
多态指的是同一种类型的事物,不同的形态。

 

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

  多态的表现 “形式之一” 就是继承:
    - 先抽象,再继承

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

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

# 动物类
class Animal:
    # 方法 吃
    def eat(self):
        pass
    # 方法 叫
    def speak(self):
        pass
# 猪类
class Pig(Animal):
    def eat(self):
        print(bia唧...)

    def speak(self):
        print(哼哼哼...)
# 猫类
class Cat(Animal):
    def eat(self):
        print(咬ji 咬ji....)
    def speak(self):
        print(喵喵喵...)
# 狗类
class Dog(Animal):
    def eat(self):
        print(舔 ji 舔ji...)
    def speak(self):
        print(汪汪汪...)

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

# 让动物们叫起来
animal1.speak()
animal2.speak()
animal3.speak()

抽象类

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(bia唧...)
    def speak(self):
        print(哼哼哼...)

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

鸭子类型

1.什么是鸭子类型?
  不同的对象,只要长得像鸭子,动作行为像鸭子,那它就是鸭子!

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

2.为什么要有鸭子类型?
  不同对象,先抽象出相同类型的方法,给他们定制一套统一的规范
  所有的类,在定义时都按照统一的规范进行编写。

  - 多态的三种表现形式:
    - 继承父类 ****
      - 耦合度高,程序的可扩展性低

    - 继承抽象类 ***
      - 耦合度极高,程序的可扩展性极低

    - 鸭子类型: *****
      - 耦合度低,程序的可扩展性高

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

# 猪类
class Pig:
    def eat(self):
        print(bia唧...)
    def speak(self):
        print(哼哼哼...)
# 猫类
class Cat:
    def eat(self):
        print(咬ji 咬ji...)
    def speak(self):
        print(喵喵喵...)
# 狗类
class Dog:
    def eat(self):
        print(舔 ji 舔ji...)
    def speak(self):
        print("汪汪汪...")

多态之炫技

# 猪类
class Pig:
    def eat(self):
        print(bia唧...)
    def speak(self):
        print(哼哼哼...)
# 猫类
class Cat:
    def eat(self):
        print(咬ji 咬ji...)
    def speak(self):
        print(喵喵喵...)
# 狗类
class Dog:
    def eat(self):
        print(舔 ji 舔ji...)
    def speak(self):
        print("汪汪汪...")

dog = Dog()
pig=Pig()
cat=Cat()

# 多态之炫技
def SPEAK(animal):
    animal.speak()

SPEAK(dog)
SPEAK(cat)
SPEAK(pig)

str1 = tank is very handsome!!!
list1 = [tank, is, very, handsome!!!]

# 自定义统计长度函数
def LEN(obj):
    return obj.__len__()

print(LEN(str1))    # 24
print(LEN(list1))   # 4

classmethod 与 staticmethod

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

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

staticmethod:
  翻译: 静态方法
  是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “非绑定方法”。

- 对象的绑定方法:
  - 由对象来调用,由谁来调用,会将谁(对象)当做第一个参数传入。

- 类的绑定方法:
  - 由类来调用,由谁来调用,会将谁(类)当做第一个参数传入。

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

# classmethod_Demo:
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):  # cls --》指的是类
        # 在类方法内部调用类产生一个实例 ---》 对象
        obj = cls(user, pwd, role)
        # 1.查看数据前,必须要通过校验
        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)
obj=DB(‘tank‘,‘123‘,‘admin‘)
obj.check_db(‘tank‘,‘123‘,‘admin‘) # 也可以,第一个传入参数依然是类,但没什么意义
# staticmethod_Demo:
class Foo:
    @staticmethod
    def func(res):
        print(res)
obj = Foo()
#对象调用非绑定方法
obj.func(123)
#类调用非绑定方法
Foo.func(1234)

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

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

# 由时间戳以及某种算法组合而成,会产生一串世界上独一无二字符串。
print(uuid.uuid4()) # f93f9c3b-eef4-4001-922e-2124b48ca7ab

内置模块:isinstance与issubclass

isinstance与issubclass是python的内置模块: *******
  - isinstance: 判断一个对象是否是另一个类的实例
    - 如果是: True
    - 如果不是: False
  - 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: 通过 “字符串” 判断对象的属性或方法是否存在。

  - getattr: 通过 “字符串” 获取对象的属性或方法。

  - setattr: 通过 “字符串” 设置对象的属性或方法。

  - delattr: 通过 “字符串” 删除对象的属性或方法。

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

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

foo_obj = Foo(10, 20)
# hasattr
# 通过字符串x 判断对象中是否有 x属性
print(hasattr(foo_obj, x))  # True
print(hasattr(foo_obj, y))  # True
print(hasattr(foo_obj, z))  # False

# getattr
res = getattr(foo_obj, x)
print(res)  # 10

# 若属性不存在,则返回默认值
res = getattr(foo_obj, z, 默认值)
print(res)  # 默认值

# setattr
setattr(foo_obj,x,40)
print(getattr(foo_obj,x)) # 40
# 为foo_obj设置一个属性z,值为30
setattr(foo_obj, z, 30)
print(hasattr(foo_obj, z))  # True

# delattr
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()
            else:
                print(输入有误!)

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

    def download(self):
        print(文件正在下载...)


file_control_obj = FileControl()
file_control_obj.run()

 以下为验证,反射中将输入输入字符创转化为方法

# 代码同上,用来测试反射里面类型变化
class choose:    
    def run(self):
        while True:
            cmd = input(请输入命令:).strip()
            if hasattr(self,cmd):
                print(getattr(self,cmd))    # 把字符串转化为方法
                # <bound method choose.load of <__main__.choose object at 0x00000000022A5F28>>
                print(type(getattr(self,cmd)))
                # <class ‘method‘>
                getattr(self,cmd)() # 运行方法
            else:
                print(输入有误)

    def load(self):
        print(load)
    def down(self):
        print(down)

obj = choose()
print(type(obj.load))   # <class ‘method‘>
obj.run()

 

python基础语法17 面向对象3 多态,抽象类,鸭子类型,classmethod与staticmethod,isinstance与issubclass,反射

原文:https://www.cnblogs.com/ludingchao/p/11950010.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!