归一化程序设计,抽象类,接口类,多态,鸭子类型

在学面向对象时,归一化程序设计,抽象类,接口类,多态,鸭子类型这些总会让人感到困扰,这里详细写下以方便复习.

归一化程序设计

我们都知道len()方法可以得出几乎所有数据类型的长度,那他究竟是什么原理呢?
其实他是一个__len__()的方法来完成的.如Hello world的长度

s = 'hello world'
print(s.__len__())
11

大部分数据类型都可以用__len__()方法

list.__len__() # 列表
tuple.__len__() # 元组
set.__len__() # 集合
dict.__len__() # 字典

这里引出归一化设计:

def my_len(obj):      # 归一化设计
    return obj.__len__()
print(my_len('abc'))
# 无论传过来的参数是什么数据类型
# 我都可以帮助你调用这个类中的__len__方法,并将结果返回给你

归一化设计 : 从原来的面向对象编程 -->面向函数编程.降低了用户的使用成本

抽象类

这里我们先定义两个类,两个类都有一个吃饭方法.

class Dog:
    def __init__(self,name):
        self.name = name
    def bash(self):
        print('%s is bashing'%self.name)
    def eat(self):
        print('%s is eating'%self.name)

class Cat:
    def __init__(self,name):
        self.name = name
    def yell(self):
        print('%s is yelling'%self.name)
    def eat(self):
        print('%s is eating'%self.name)

对于猫和狗来说,他们吃饭的方法是一样的,我们可以从这些类当中抽象出一个类,里头有一个吃饭方法,并让其他有这个方法的类去继承这个类.
我们导入ABCMeta,abstractmethod模块,这是一个抽象的方法

from abc import ABCMeta,abstractmethod
class Animal(metaclass=ABCMeta):  # metaclass 元类  metaclass = ABCMeta表示Payment类是一个规范类
    @abstractmethod  # @abstractmethod表示下面一行中的eat方法是一个必须在子类中实现的方法
    def eat(self):pass


class Dog(Animal):
    def __init__(self,name):
        self.name = name
    def bash(self):
        print('%s is bashing'%self.name)
    def eat(self):
        print('%s is eating'%self.name)

class Cat(Animal):
    def __init__(self,name):
        self.name = name
    def yell(self):
        print('%s is yelling'%self.name)
    def eat(self):
        print('%s is eating'%self.name)

抽象类主要就是作为基类/父类,来约束子类中必须实现的某些方法
抽象类的特点:

  1. 必须在类定义的时候指定metaclass = ABCMeta
  2. 必须在要约束的方法上方加上@abstractmethod方法

这里提一个重点: 抽象类不能实例化

接口类

在说接口类之前,先提一下python和java两种语言之间多继承的区别:

  • java 不支持多继承
  • python 支持多继承 :通过抽象类的多继承来实现复杂的规范

再举一个例子,动物园里有三个类,天鹅,狮子,鹦鹉,天鹅会飞,走,游泳,狮子会走和游泳,而鹦鹉会飞会走还会说话.
但是不同动物的相同行为是不能混为一谈,不同动物却有相同行为
这里我们写飞动物,游泳动物,走动物三个类并分别在里头写飞,游泳,走方法,让三个动物类分别继承他

from abc import ABCMeta,abstractmethod
class Fly_Animal(metaclass=ABCMeta):
    @abstractmethod
    def fly(self):
        print('爷会飞')
class Swim_Animal(metaclass=ABCMeta):
    @abstractmethod
    def swim(self): pass
class Walk_Animal(metaclass=ABCMeta):
    @abstractmethod
    def walk(self): pass

class Swan(Fly_Animal,Swim_Animal,Walk_Animal):
    def fly(self):
        super().fly()
        print('飞')
    def walk(self):print('走')
    def swim(self):print('游')

class Lionr(Walk_Animal,Swim_Animal):
    def walk(self):print('走')
    def swim(self):print('游')

class Parrot(Fly_Animal,Walk_Animal):
    def fly(self):print('飞')
    def walk(self):print('走')
    def talk(self):print('说')

接口类更接近java中的接口的概念
而python中由于有了抽象类的多继承,不需要接口的概念了
接口类其实就是一个基类写出来被子类多继承

多态

python中处处是多态,他是一个自带多态的语言.
多态是同一个行为具有多个不同表现形式或形态的能力
我们举一个简单的例子,我们比方说一个软件,他有普通用户,普通用户之下又有vip,svip,vvip各种用户形式,vip,svip,vvip都是基于普通用户而出现的,服务于普通用户,这里我们将vip,svip等这些普通用户所演化的多种形态称为多态.
再比如说,支付表现出了多种状态:

  • 支付宝
  • 微信
  • apple pay
class Payment(object):pass
class Alipay(Payment):
    def pay(self,money):
        pass
class Wechatpay(Payment):
    def pay(self,money):
        pass
class Applepay(Payment):
    def pay(self,money):
        pass
def pay(person_obj,money):
    person_obj.pay(money)
wang = Alipay()
pay(wang,200)
quan = Wechatpay()
pay(quan,300)

不同的类,做相同(方法)的调用,产生不同的结果,这里表现出来的一个payment类表现出来的多种支付状态就称为多态,且不同于静态语言(例如Java),python(动态语言)调用实例方法,不检查类型,只要给了参数且方法存在且正确,就可以调用.
借用一句话,多态用一句话概括就是,有这种方法,并且传入相应的参数

鸭子类型

来讲讲起源,Duck typing 这个概念来源于美国印第安纳州的诗人詹姆斯·惠特科姆·莱利(James Whitcomb Riley,1849-1916)的诗句:”When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.” 当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。这个概念有点让人头晕,我简单说.

在鸭子类型中,我们关注的不是对象类型的本身,而是他是如何使用的.这里我们再讲len这个方法,我们已经知道了len这个函数的内部机制,然而对于len()函数来说,无论你给的是list,str,dict或者set这些类型,他都不会关注,而你只要是能计算出长度的参数(能用__len__方法的),我(len()函数)就接受.抽象的说,数据集合就是鸭子,而list,str,dict等这些就是鸭子类型(具有数据集合的所有特性,但却不能说他就是数据集合,他表现的像是一个数据集合,一个能计算出长度的数据集合).

总结

说了这么多,这些其实都是一个中心思想:不同类之间的相同的方法都应该用同一个名字.
稍微分辨一下就是归一化设计是为了使用不同类中的方法,而要求 不同类之间的相同的方法都应该用同一个名字
而多态是已经实现了"不同类之间的相同的方法都用同一个名字",解决不同类的对象的传参问题
最后是鸭子类型是不需要解决类的对象的传参问题,就可以直接利用已经实现的"不同类之间的相同的方法都用同一个名字"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值