• 初识面向对象三(经典类/多态/鸭子类型/初识封装)



    py2中的经典类
    coding:utf-8

    class D:
    pass
    # def func(self):
    # print('d')
    class B(D):
    pass
    # def func(self):
    # print('b')
    class C(D):
    pass
    def func(self):
    print('c')
    class A(B,C):
    pass
    # def func(self):
    # print('a')
    a = A()
    a.func()
    python2.x中的经典类
    多继承中深度优先
    没有mro提示你顺序
    没有super

    python2中的新式类 基本和python3中的新式类相似
    class D(object):
    pass
    def func(self):
    # print('d')
    class B(D):
    pass
    def func(self):
    print('b')
    class C(D):
    pass
    def func(self):
    super(C,self).func()
    print('c')
    class A(B,C):
    pass
    # def func(self):
    # print('a')
    a = A()
    a.func()
    print(A.mro()) # 方法
    print(A.__mro__) # 属性

    python2.x版本中存在两种类
    经典类
    不主动继承object类的所有类都是经典类
    继承关系遵循深度优先算法
    没有mro,没有super
    新式类
    所有继承object类的都是新式类
    和py3一样继承遵循mro顺序和c3算法
    有mro方法,但是super的使用必须传参数super(子类名,对象名).方法名

    python3.x中的类和py2.x中的新式类有什么区别???
    不需要主动继承object
    py3中super()可以直接用,py2中使用必须传参数super(子类名,对象名).方法名

    所有继承了object类的都是新式类 <==> 所有的新式类都继承object类
    PEP8规范 : 跨环境 无论在py2还是py3中定义一个新式类,都需要加上object这个继承
    class 类名(object):
    pass
    class 子类(类名):
    pass

    python中处处是多态
    python是一门自带多态的语言

    java
    强数据类型的语言
    def pay(float money): # float 2.35 - 类 对象
    print(money)
    pay()

    class Payment(object):pass
    class Alipay(Payment):
    def pay(self,money):
    pass
    class Wechatpay(Payment):
    def pay(self,money):
    pass
    def pay(Payment person_obj,float money):
    person_obj.pay(money)
    alex = Alipay()
    pay(alex,24.5)
    yuan = Wechatpay()
    print(yuan,23.5)
    一个类表现出来的多种状态
    支付Payment是一个类,多种状态: 使用阿里支付Alipay,使用微信支付Wechatpay
    支付表现出来的多种状态 :
    第一种状态 支付宝支付
    第二种状态 微信支付
    class Animal(object):pass
    class Cat(Animal):
    def eat(self):pass
    class Dog(Animal):
    def eat(self):pass
    def eat(Animal obj):
    obj.eat()
    小花 = Cat() # 小花就是猫类的对象 类==类型==数据类型,小花的类型就是Cat
    小黑 = Dog()
    eat(小花)
    eat(小黑)
    int str list tuple dict set 内置的数据类型
    Cat Dog Animal 自定义的类/数据类型
    动物吃表现出来的多种状态:
    猫吃
    狗吃

    python
    class Cat(object):
    def eat(self):pass
    class Dog(object):
    def eat(self):pass
    def eat(obj):
    obj.eat()
    小花 = Cat() # 小花就是猫类的对象 类==类型==数据类型,小花的类型就是Cat
    小黑 = Dog()
    eat(小花)
    eat(小黑)
    动物吃表现出来的多种状态:
    猫吃
    狗吃

    class Alipay(object):
    def pay(self,money):
    pass
    class Wechatpay(object):
    def pay(self,money):
    pass
    def pay(person_obj,money):
    person_obj.pay(money)
    alex = Alipay()
    pay(alex,24.5)
    yuan = Wechatpay()
    print(yuan,23.5)
    pay('abc',23.5)

    总结
    在python中体现的多态:
    几个类拥有同名的方法,可以写一个函数,来统一进行调用 - 归一化设计
    java要要求传递数据的数据类型? (通过继承来实现的)
    是为了代码不出错,只要你能够顺利的调用这个函数,那么内部的执行就大大降低出错的概率
    python却不要求?
    更多的不是硬性的规定,但是可能会因为传递的参数不符合规则而使得代码报错,但是大大降低了代码繁琐程度

    
    
    python特有的  鸭子类型是相对论
    len()这个函数来说: str list dict set tuple 都是鸭子类型
    鸭子 == 数据集合
    对于len来说,它不关心给我的是一个具体的什么数据类型
    只关心 能够计算长度的就是我接受的参数

    在java中 用多态实现的
    def len(object obj):
    print('*'*20)
    return obj.__len__()

    print(len('abcd'))
    print(len([1,2,3]))

    在python中 用鸭子类型
    不关心这个对象的数据类型,只要这个对象含有一个__len__就可以了
     对于len函数来说,含有__len__的所有的类都是鸭子类型
    def len(obj):
    print('*'*20)
    return obj.__len__()

    print(len('abcd'))
    print(len([1,2,3]))


    class Cat():
    def eat(self):pass
    def sleep(self):pass
    def drink(self):pass
    def play(self):pass
    class Dog():
    def eat(self):pass
    def sleep(self):pass
    def drink(self):pass
    def play(self):pass
    Cat和Dog就认为是鸭子类型
    绝对的像 : 狗有的猫都有


    class Cat():
    def eat(self):pass
    def sleep(self):pass
    def drink(self):pass
    def climb(self):pass
    class Dog():
    def eat(self):pass
    def sleep(self):pass
    def drink(self):pass
    def ball(self):pass
    eat
    sleep

    class Cat():
    def eat(self):pass
    def climb(self):pass
    class Dog():
    def eat(self):pass
    def ball(self):pass
    eat cat和dog还是鸭子类型


    鸭子类型
    是python语言中特有的,不依赖于继承和规范来进行的一种约定(依赖继承和规范特指:java中的多态和接口)
    如果两个类都需要做某一件事情,那么应该起相同的名字,这个时候,对于做的这件事情来说,这两个类就变成了鸭子类(归一化设计的表现)


    中心思想 : 不同类之间的相同的方法都应该用同一个名字

    抽象类 规范 : 不同类之间的相同的方法都应该用同一个名字
    接口类 规范: 不同类之间的相同的方法都应该用同一个名字
    class Cat():
    def eat(self):pass
    class Dog():
    def eat(self):pass
    def eat(obj):
    obj.eat()
    归一化设计 :为了使用不同类中的方法,而要求 不同类之间的相同的方法都应该用同一个名字

    class Animal:pass
    class Cat(Animal):
    def eat(self):pass
    class Dog(Animal):
    def eat(self):pass
    def eat(Animal obj):
    obj.eat()
    多态 : 已经实现了"不同类之间的相同的方法都用同一个名字",解决不同类的对象的传参问题

    class Cat:
    def eat(self):pass
    class Dog:
    def eat(self):pass
    def eat(obj):
    obj.eat()
    鸭子类型 : 不需要解决类的对象的传参问题,就可以直接利用已经实现的"不同类之间的相同的方法都用同一个名字"


    初识封装
    什么是封装?
    广义上(大家认为的) :
    把一类事务的相同的行为和属性归到一个类中
    class Dog:
    def bite(self):pass
    狭义上(学术上的定论) :
    把一些特殊的属性和方法藏在类中
    外部无法调用,只有内部可以调用
    class Dog:
    def bite(self):pass
    dog = Dog()
    dog.bite() # 从一个类的外部调用了bite方法

    class Dog:
    dog_sum = 0
    def __init__(self):
    self.count() # 从一个类的内部调用了count方法
    def count(self):
    Dog.dog_sum += 1

    alex = Dog()
    print(Dog.dog_sum)

    alex.count() # # 从一个类的外部调用了count方法
    alex.count()
    alex.count()
    print(Dog.dog_sum)

    隐藏静态属性
    class Dog:
    # dog_sum = 0 # 不安全,因为这个属性可以在类的外部被随便修改
    __dog_sum = 0 # 安全,通过dog_sum方法和__变量名让属性变成只能看不能改的值
    def __init__(self):
    self.count()
    def count(self):
    Dog.__dog_sum += 1 # 可以从一个类的内部使用__dog_sum的属性
    def dog_sum(self):
    return Dog.__dog_sum

    print(Dog.__dict__)
    alex = Dog()
    print(Dog.__dict__)
    # print(Dog.__dog_sum) # 不可以从外部直接使用这个变量
    print(alex.dog_sum())

    class Dog:
    __dog_sum = 0 # 私有的静态属性 _Dog__dog_sum
    def __init__(self):
    self.count()
    def dog_sum(self):
    return Dog.__dog_sum # 只要是在类的内部使用__名字,默认就被改成 _类名__名字

    print(Dog.__dict__)
    print(Dog._Dog__dog_sum) # 绝不能在后续我们的代码中出现这种情况
    只要是在类的内部的名字前面加上双下划线
    那么这个名字 就变成 私有的 (只能在类的内部使用,不能在类的外部使用)
    在定义的时候,存储的名字就会发生变化 _类名__名字
    因此 在类的外部就不会被调用到了
    在类的内部 使用__名字,默认就被改成 _类名__名字

    class Dog:
    # dog_sum = 0 # 不安全,因为这个属性可以在类的外部被随便修改
    __dog_sum = 0 # 安全,通过dog_sum方法和__变量名让属性变成只能看不能改的值
    def __init__(self):
    self.__count()
    def __count(self):
    Dog.__dog_sum += 1 # 可以从一个类的内部使用__dog_sum的属性
    def dog_sum(self):
    return Dog.__dog_sum

    alex = Dog()
    print(alex.dog_sum())
    yuan = Dog()
    print(yuan.dog_sum())

    class Dog:
    def __init__(self,name,password):
    self.__name = name # 不希望某个值被随便修改
    self.__password = password # 不希望某个值被从类的外部看到
    def login(self,usr,pwd):
    if usr == self.name and pwd == self.__password:
    return True
    def name(self):
    return self.__name
    def set_name(self,new_name):
    if type(new_name) is str:
    self.__name = new_name

    alex = Dog('alex','sb123')
    print(alex.login('alex','sb222'))
    print(alex.login('alex','sb123'))

    print(alex.name())
    alex.set_name('alex_sb')
    print(alex.name())

    只能在类的内部被调用,保证了类内部数据的安全,不会被别人随意修改
    私有静态属性 : 为了不随意被外部修改
    私有方法 : 不希望被外部随意调用
    私有的对象属性 :
    不希望某个值被随便修改
    不希望某个值被从类的外部看到

    封装的继承
    子类不能继承父类的私有方法
    class Foo(object):
    A = 123
    __私有的静态变量 = 'ABC' # _Foo__私有的静态变量
    print('---> ',__私有的静态变量) # 在类的内部使用 _Foo__私有的静态变量

    class Son(Foo):
    def func(self):
    print('--> 1 ',Son.A) # 子类没有找父类,能找到
    print('--> 2 ',Foo.__私有的静态变量) # 子类没有找父类,找不到"_Son__私有的静态变量"
    # print(Foo.__私有的静态变量)
    Son().func()

    __这个变量出现在哪个类中,就会在变形的时候 加上这个类的类名
    所以在子类中使用私有的名字,会加上子类的名字
    这样就不可能调用加上了父类名字的静态变量了

    class Foo(object):
    def __func(self): # self._Foo__func
    print('in foo')

    class Son(Foo):
    def wahaha(self):
    self.__func() # self._Son__func,不能在子类的内部使用父类的私有方法

    s = Son()
    s.wahaha()

    class Foo(object):
    def __init__(self):
    self.__func() # _Foo__func
    # self.func()

    def __func(self):print('in Foo __func') # _Foo__func

    def func(self):print('in Foo func')

    class Son(Foo):
    def __func(self):print('in Son __func') # _Son__func

    def func(self):print('in Son func')

    Son()

    调用私有的方法或者属性
    不需要考虑self是谁的对象
    只要是私有的方法或者属性,就一定是在调用的当前类中执行方法

    当某个方法或者属性,不希望被子类继承的时候,也可以把这个方法属性定义成私有成员






  • 相关阅读:
    下划线的学习4
    下划线的学习3
    下划线的学习2
    下划线的学习1
    小程序登录 之 支付宝授权
    开发第一个flutter程序 hello world
    flutter 环境安装以及配置
    地图组件上的自定义区域叠加层显示 ArcGis + GeoJson
    Netty+MUI从零打造一个仿微信的高性能聊天项目,兼容iPhone/iPad/安卓
    linux 下的emoji在MariaDB中的字符集修改
  • 原文地址:https://www.cnblogs.com/Godisgirl/p/10014133.html
Copyright © 2020-2023  润新知