Python继承

2022-07-27,

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

1.继承

面向对象编程 (OOP) 语言的一个主要功能就是“继承”,所谓继承就是使现有的类无需编码便可以拥有原有类的方法和属性。

被继承的类可以称之为***父类、基类、超类***。继承的类可以称之为***子类、派生类***。派生和继承是一体两面,从父类向子类看就是派生,从子类向父类看就是继承。子类和父类的关系可以用“is a”类表示,即子类是父类的一种,是一个更具体、更加强大的父类。python支持单继承和多继承。

继承的优点:

  • 可以简化代码,减少冗余度
  • 提高了代码的可维护性
  • 提高了代码的安全性

1.1 单继承

所谓的单继承就是一个子类只有一个父类。子类会继承父类所有的属性和方法。

  • 私有成员在子类中无法直接使用
  • 子类对象无法直接使用继承自父类的私有成员
  • 子类方法和父类方法重名,通过子类对象调用的是子类方法
#语法:
class 子类名(父类名):
    pass

注意:object是Python中所有类的父类【一般情况下,如果一个类没有指明的父类,默认它的父类为object】

  • 构造函数的继承

    class Animal:
        def __init__(self,name,age):
            self.name = name
            self.__age =age
    	....
    
    class Dog(Animal):
        def __init__(self,name,age,gender):
            #调用父类构造方法的好处,简化了子类构造方法代码,实现了代码复用
            #1. super(当前类名,self).__init__(实参列表) #实参不要带self
            # super(Dog,self).__init__(name,age)
            # 2. super().__init__(实参列表)#实参不要带self
            # super().__init__(name, age)
    
            #3. 父类名.__init__(self,其它参数)
            Animal.__init__(self,name,age)
            self.gender = gender
    	....
    
  • 方法的改写

    class Animal:
        def __sleep(self):
            print('睡饱饱')
        def eat(self):
            print('吃饭饭')
        def sleeping(self):
            self.__sleep()
    	....
    class Dog(Animal):
    	#改写继承自父类的方法
        def eat(self):
            # Animal.eat(self)
            super().eat()
            print('香香的大骨头')
        #添加新方法
        def bark(self):
            print('别跑,爷咬不死你')
            # print(self.age)
    dog = Dog('泰迪',5,'公')
    dog.eat()  #优先调用子类方法
    dog.sleeping()  #子类没有,则调用父类方法,一直找到object都没有,则报错
    
  • 方法添加

1.2 多继承

一个子类可以有多个父类。语法:

class 子类类名(父类1,父类2....):
	子类类体

2.类成员

类成员包括:类属性和类方法,不同于成员属性和成员方法属于对象,类属性和类方法属于类,可以不实例化对象,直接通过类名调用,这些类成员为所有对象共有,一般用于对象间通信。

  • 在程序运行期间类属性始终存在

  • 类属性

    class Person:
        #类属性
        name = '无名氏'
        gender = '男'
        __age = 0   #私有类属性
    
        def __init__(self,name,age):
            self.name = name  #实例属性或成员属性
            self.__age = age
    
    #实例化对象
    zhang = Person('张三',20)
    #类属性调用方式  
    #调用方式:类名.属性名  对象.属性名
    print(Person.name)  #类属性可以不实例化对象调用
    print(zhang.gender)
    
    print(Person.__age)  # 私有类属性不能通过类名直接调用
    #访问的优先级  成员属性高于类属性
    #如果成员属性名和类属性名冲突,优先访问成员属性,成员属性屏蔽类属性
    #应该尽量避免成员属性和类属性重名
    print(zhang.name)  #张三
    
    #删除对象的属性
    del zhang.name
    print(zhang.name)  #无名氏  访问的是类属性 
    
  • 类方法和静态方法

    • 类方法属于类,为所有对象共有,可以通过类名或对象调用
    • 类方法可以用来访问类属性
    • 静态方法属于类的作用域内的全局函数
    • 类方法和静态方法的区别,类方法第一个参数是类对象,由系统传入,静态方法没有
    • 共同点:静态方法和类方法都可以通过类名直接调用,属于类,不属于对象
class Date:
      def init(self,year,month,day):
          self.year = year
          self.month = month
          self.day = day
          
      @classmethod     #类方法
      def date_from_string(cls,date_string):
          '''
          :功能:根据传入字符串创建日期对象
          :param cls 类对象,和类名作用一样
          :param date_string: 日期字符串,格式必须是yyyy-mm-dd
          :return: 日期对象
          '''
          year,month,day = tuple(map(int,date_string.split('-')))
          return cls(year,month,day)

      @staticmethod
      def is_valid_date(date_string):
          year,month,day = tuple(map(int,date_string.split('-')))
          return year >= 0 and 1 < month <= 12 and 0< day <=31

  d1 = Date.date_from_string('2018-05-29')
  print(d1.year,d1.month,d1.day)
  print(Date.is_valid_date('2018-5-29'))

3 实例成员的动态绑定(了解)

实例的属性和方法都可以动态绑定,也就是可以在程序运行期间可以给程序增加功能,这对于那些静态语言来说无异于天方夜谭,但对python来说一切皆有可能

  • 给对象动态添加的属性只属于这个对象,其它对象没有该属性
  • 使用__ slots__限制属性的动态绑定:
class Cat:
    __slots__ = ('gender','name','age','kind')  #这个类的对象这能有这些属性
	
cat = Cat()

#1.动态绑定属性
cat.name = 'tom'
cat.gender = '公'  #动态添加的属性
#cat.weight = 8  #不能添加这个属性,语法错误

定义一个函数,第一个参数要是self
def walk(self):
    print(self.name)
    
cat.walk = walk
cat.walk(cat)  #怪胎

#2.给对象绑定方法
from types import  MethodType  #引入types模块中的MethodType
cat.walk = MethodType(walk,cat)   #给cat对象绑定walk方法
cat.walk()


#3.给类绑定实例方法 ,所有对象都可以使用
Cat.walk = walk
cat1 = Cat()
cat1.name = 'jerry'
cat1.walk()

4. 系统魔术方法

4.1 __init____new__

  • __ new__ 用于创建一个对象,有返回值;__new__是类方法;__ init__ 用于初始化对象,没有返回值

  • __new__默认参数是cls,系统传递的是类名,__init__默认参数是self,系统传递的是当前对象

  • __ new__ 先于__ init__ 执行

    class Dog:
        def __new__(cls, *args, **kwargs):
            print('new方法在执行')
           // return super().__new__(cls,*args, **kwargs)   #必须通过父类的__new__创建对象
            return object.__new__(cls,*args, **kwargs)
            
        def __init__(self,name,age):
            self.name = name
            self.__age = age
            print('init方法在执行')
    

4.2 算数运算符重载

在python中自定义类的对象也可以象系统类型一样完成+、-、*、/、索引、切片等运算,这有赖于python类有运算符重载功能。

class MyTime:

    def init(self,hour,minute,second):
        self.hour = hour
        self.minute = minute
        self.second = second
    def __add__(self, other):
        if not isinstance(other,self.class):
            raise TypeError('Not a MyTime')
        second = self.second + other.second
        minute = self.minute + other.minute + second // 60
        hour = (self.hour + other.hour + minute // 60) % 24
        return self.__class__(hour,minute % 60,second % 60)
    #+=
    def __iadd__(self, other):
        self = self.__add__(other)
            
    def __str__(self):
       return "{}:{}:{}".format(self.hour,self.minute,self.second)
            
t1 = MyTime(5,34,45)
t2 = MyTime(8,45,34)
res = t1 + t2  #t1.__add__(t2)
print(res)
t1 += MyTime(3,20,10)
print(t1)

4.3 迭代器

如果想让一个类用于for-in 循环则必须实现__ iter__ 和__ next__ 方法

class Fib:
    def __init__(self):
        self.x = 0
        self.y = 1
    def __iter__(self):
        return  self  #返回当前对象
    def __next__(self):
        self.x ,self.y = self.y, self.x + self.y   #迭代公式
        if self.x > 1000:
            raise StopIteration()
        return  self.x 

4.4 __call__

​ 如果一个类实现了__call__(slef, [,*args [,**kwargs]])方法,则该类的对象可以象函数一样调用。它是实现类装饰器的基础

class Demo:
    def __call__(self, *args, **kwargs):
        print("我是函数,不过是假冒的")

d1 = Demo()
d1()
  • 类装饰器
class Decrator:
    def __call__(self, func):
        def inner():
            func()
            print("*"*50)
        return inner

@Decrator()
def test():
    print("我是你们的小可爱")

5.单例设计模式

2.1、设计模式概述

  1. 概念:对特定问题的一种解决方案,和平台、语言无关
  2. 作用
    • 更好的理解面向对象
    • 让你的代码更加优雅
    • 使你的代码更加容易扩展和复用
    • 面试时候的重点

设计模式的一些基本原则

  • 高内聚,低耦合
  • 单一职责
  • 开闭原则(对修改封闭、对扩展开放)

2.2 单例

所谓

单例也就是一个类只生成一个对象,无论你实例化多少对象,都是同一个对象

  • 应用场景:数据库操作类,文件操作类等,可以减少资源的占用

2.3 实现

  • 使用__new__
  class Singleton:
      __instance = None   # 保存实例的引用
      def __new__(cls, *args, **kwargs):
          if cls.instance is None:  # 如果实例没有实例化
              cls.__instance = object.__new__(cls,*args,**kwargs)  #实例化对象,将引用存到__instance
          return  cls.__instance #返回对象
  s1 = Singleton()
  s2 = Singleton()
  print(id(s1),id(s2))
  if s1 is s2:
      print('单例')

本文地址:https://blog.csdn.net/weixin_44799030/article/details/109915314

《Python继承.doc》

下载本文的Word格式文档,以方便收藏与打印。