博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面向对象:继承、多态、封装
阅读量:7282 次
发布时间:2019-06-30

本文共 5596 字,大约阅读时间需要 18 分钟。

类、对象:

  • 类:抽象的
  • 对象:具体的
class Person:  # 类名    def __init__(self, name, hp, aggr, gender):    # __init__为初始化方法        self.name = name        self.hp = hp        self.aggr = aggr        self.gender = gender    def walk(self, n):  # 定义方法,一般情况下必须传self参数,且必须写在第一个;后面还可以传其他参数,想传多少就多少        print("{}走了{}步".format(self.name, n))p = Person("王者", "100", "5", "男")  # 对象 = 类(参数),这个过程叫实例化print(p.name)      # 查看属性值print(p.__dict__)  # 查看所有属性p.walk(10)         # 调用这个对象拥有的方法
初识类

类有静态属性和方法,类中的静态属性和方法可以被对象和类调用。

class Person(object):    money = 0    def work(self):        Person.money += 100mother = Person()father = Person()mother.work()father.work()print(Person.money)  #200
共享静态属性例子

类的组合:在一个类中以另外一个类的对象作为数据属性

class Car:    """一次模拟汽车的简单尝试"""    def __init__(self, make, model, year):        self.make = make        self.model = model        self.year = yearclass Battery:    """一次模拟电动汽车电瓶的简单尝试"""    def __init__(self, battery_size=70):        """初始化电瓶的属性"""        self.battery_size = battery_size    def describe_battery(self):        """打印一条描述电瓶容量的消息"""        print("This car has a " + str(self.battery_size) + "-kWh battery.")class ElectricCar(Car):    """电动汽车特殊之处"""    def __init__(self, make, model, year):        """初始化父类的属性,再初始化电动汽车特有的属性"""        super().__init__(make, model, year)        self.battery = Battery()my_tesla = ElectricCar("tesla", "model s", 2016)my_tesla.battery.describe_battery()  #This car has a 70-kWh battery.
View Code

面向对象三大特性:继承、多态、封装

继承

继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又称为基类或超类,新建的类这时可称为子类或派生类

python中类的继承分为:单继承和多继承

  一个类可以被多个类继承

  一个类可以继承多个父类(python独有)

class A(object):  # 定义父类    passclass B(object):  # 定义父类    passclass C(A):       # 单继承,父类是A,子类是C    passclass D(A,B):     # 多继承(python独有),用逗号分隔开多个继承的类    pass########## 查看继承 ########### __base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类print(D.__base__)     # 
print(D.__bases__) # (
,
)#在python3中,没有继承父类就默认继承objectprint(A.__bases__) # (
,)
继承

派生

  • 父类中没有的属性,在子类有,叫做派生属性
  • 父类中没有的方法,在子类有,叫做派生方法

注意:

  子类可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),一旦重新定义了自己的属性且与父类重名,调用时就以自己为准;

  要是子类的对象调用属性,子类中有的名字就用子类的, 子类中没有才找父类的, 如果父类也没有就报错

在python3中,子类执行父类的方法也可以直接用super方法(super方法只在python3中存在)

class Base1(object):    def func(self):        print("Base1.func")class Base2(object):    def func(self):        print("Base2.func")class Foo(Base1, Base2):    def func(self):        # 方式一:根据mro的顺序执行方法        super().func()           # Base1.func        super(Foo, self).func()  # Base1.func        # 方式二:主动执行父类类的方法        Base2.func(self)         # Base2.func        print("Foo.func")obj = Foo()obj.func()              # Foo.funcsuper(Foo, obj).func()  # Base1.func  在类外调用父类方法print(Foo.mro())  # [
,
,
,
]

继承顺序:

单继承:子类有的用子类,子类没有就用父类

多继承:
  经典类中:深度优先
  新式类中:广度优先

python2.7中: 经典类、新式类共存,新式类要继承object

python3中:    只有新式类,默认继承object

super的本质(python3才有,即只有新式类,广度优先):不是单纯找父类,而是根据调用者的节点位置的广度优先顺序来的

class A(object):    def func(self):        print("A")class B(A):    def func(self):        super().func()        print("B")class C(A):    def func(self):        super().func()        print("C")class D(B,C):    def func(self):        super().func()        print("D")d = D()d.func()print(D.mro())  # mro()方法可查看类的继承顺序# [
,
,
,
,
]

多态

多态指的是一类事物有多种形态

动物有多种形态:人、狗、猪

import abcclass Animal(metaclass=abc.ABCMeta):  # 动物类    @abc.abstractmethod    def talk(self):        passclass People(Animal):  # 动物的形态之一:人    def talk(self):         print("你好!")class Dog(Animal):  # 动物的形态之二:狗    def talk(self):        print("旺旺!")class Cat(Animal):  # 动物的形态之三:猫    def talk(self):        print("喵喵!")
View Code
# 类List与类Tuple都有相似的方法,那么这两个类就是鸭子类型,都可以使用len()方法,而不需要像其他语言一样告诉len()自己是什么类型# 在强类型语言中,叫多态# 在python中,叫鸭子类型class List(object):    def __len__(self):        passclass Tuple(object):    def __len__(self):        passdef len(obj):    return obj.__len__()l = List()  # 或者T = Tuple()len(l)
鸭子类型

封装

隐藏对象的属性和实现细节,仅对外提供公共访问方式。

好处:

  1.将变化隔离;
  2.便于使用;
  3.提高复用性;
  4.提高安全性。

封装原则:

  1.将不需要对外提供的内容都隐藏起来;
  2.把属性都隐藏,提供公共方法对其访问。

在python中用双下划线开头的方式将属性隐藏起来(设置成私有属性)

class Person:    __country = "china"   # 私有静态属性    def __init__(self, name, age):        self.name = name        self.__age = age  # 私有实例属性    def __get_age(self):  # 私有方法        return self.__age    def func(self):        return self.__get_age()  # 调用私有xx的正确方式p = Person("pd", 18)print(p.func())          # 正确使用方式# print(p._Person__age)  # 对象._类名__属性名(不建议这样使用!!!)
私有xx

封装与扩展性

封装在于明确区分内外,使得类设计者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。

class Person(object):    def __init__(self, name, age):        self.name = name        self.__age = age    def get_age(self):        return self.__age    def set_age(self, n):        if 0 < n and n.isdigit():            self.__age = n        else:            return "年龄不合法"p = Person("pd", 18)print(p.get_age())     # 18print(p.set_age(-18))  # 年龄不合法
View Code

会用到私有的这个概念的场景:

  1.隐藏一个属性,不让类的外部直接调用

  2.保护一个属性,不让属性随意被改变
  3.保护一个属性,不被子类继承

小结

接口类、抽象类:

  python中没有接口类,有抽象类,abc模块中的metaclass = ABCMeta,@abstructmethod
  本质是做代码规范用的,希望在子类中实现和父类方法名字完全一样的方法

接口类与抽象类的区别:

  在java的角度上看是有区别的
    java没有多继承,所以为了接口隔离原则,设计了接口这个概念,以便实现多继承;
    java本来就支持单继承,所以就有了抽象类。
  python既支持单继承也支持多继承,所以对于接口类和抽象类的区别就没有那么明显;python中没有内置接口类

多态与鸭子类型:

  多态 --> python天生支持多态
  鸭子类型 --> 不依赖父类的情况下实现两个相似的类中的同名方法

 

转载于:https://www.cnblogs.com/believepd/p/9643471.html

你可能感兴趣的文章
vue-cli的安装使用
查看>>
js实现页面重定向
查看>>
js数组
查看>>
点滴积累【other】---HTTP 错误 404.13 - Not Found,请求筛选模块被配置为拒绝超过请求内容长度的请求(转载)...
查看>>
C与C++,面向过程与面向对象
查看>>
第37件事 极简设计的3个方面
查看>>
Docker安装(yum方式 centos7)
查看>>
运算符
查看>>
一个简单的转换字母大小写的方法
查看>>
hibernate中evict()和clear()的区别
查看>>
学习web components
查看>>
PHP 将秒数转换成时分秒
查看>>
node.js 模块加载原理
查看>>
一个自定义线程池的小Demo
查看>>
Report_SRW工具的基本用法(概念)
查看>>
dedecms设置文章分页后,标题会带有序号的解决方法
查看>>
MySQL复制
查看>>
模式识别之相似度计量---余弦计算相似度度量关于两句话的相似度
查看>>
Django之ORM相关操作
查看>>
SVN 安装后报不是内部或外部命令
查看>>