Python09_面向对象

声明

文章是基于:

哗哩哗哩上的《黑马程序员python教程,8天python从入门到精通,学python看这套就够了》视频教程所做的学习笔记,仅为学习使用!!如有侵权,联系删除

目录

面向对象编程

一、初始对象

(一)设计类(class)

(二)创建对象

(三)对象属性赋值

二、成员方法

(一)类的定义和使用

(二)成员变量和成员方法

(三)成员方法的定义语法

三、类和对象

(一)语法

(二)基于类创建对象

四、构造方法

(一)属性(成员变量)的赋值

(二)构造方法

五、其他内置方法

(一)魔术方法

1、__str__字符串方法

2、__lt__小于符号比较方法

3、__le__小于等于符号比较方法

4、__eq__比较运算符实现方法

六、封装

(一)定义

(二)私有成员

(三)使用私有成员

(四)练习

七、继承

(一)单继承

(二)多继承

(三)复写

(四)调用父类同名成员

八、类型注解

(一)变量的类型注解

(二)容器的类型注解

1、基础容器类型注解

2、容器类型详细注解

(三)注释的类型注解

(四)函数(方法)的类型注解

1、形参注解

2、返回值注解

(五)Union类型

九、多态

(一)抽象类(接口)


面向对象编程

  • 核心在于以对象为编程单位
  • 它把相关的数据(对象的属性)相关功能(对象的方法)集合在一起,放在类和对象这个机制里。
  • 这样在编程中可以以对象为单位,而不用以一行一行的代码为单位来展开了。

一、初始对象

使用变量记录数据太乱了,如果程序和生活中一样:

  • 可以设计表格

  • 可以将设计的表格打印出来

  • 可以将打印好的表格供人填写内容

那么数据的组织就非常方便了

(一)设计类(class)

  • 在程序中设计表格

  •  Class Student:
         name = None # 记录学生姓名

(二)创建对象

  • 在程序中打印生产表格

  •  # 基于类创建对象
     stu_1 = Student()
     stu_2 = Student()

(三)对象属性赋值

  • 在程序中填写表格

  •  stu_1.name = "周杰伦"  # 为学生1对象赋予名称属性值
     stu_2.name = "林俊杰"  # 为学生2对象赋予名称属性值

二、成员方法

(一)类的定义和使用

  • 使用类去封装属性,并基于类创建出一个个的对象来使用

  • 类的使用语法:

    • class是关键字,表示要定义类了

    • 类的属性,即定义在类中的变量(成员变量)

    • 类的行为,即定义在类中的函数(成员方法)

  • 创建类对象

(二)成员变量和成员方法

  • 其中:

    • 类中定义的属性(变量),我们称之为:成员变量

      • ​​​​​​​他是归属于类的一个变量用来描述类的一些特性

    • 类中定义的行为(函数),我们称之为:成员方法

(三)成员方法的定义语法

  • self关键字:必须填写的

    • 用来表示类对象自身的意思

    • 我们使用类对象调用方法时self会自动被python传入

    • 成员方法内部,想要访问类的成员变量必须使用self

    •  def say_hi(self):
           print(f"hi大家好,我是{self.name}")
  • self关键字,尽管在参数列表中,但是传参的时候可以忽略

    • 传参时,self是透明的,不用理会

三、类和对象

使用程序中的类,可以完美的描述现实世界的事物

(一)语法

1、Python中使用class关键字来定义类,遵循下述格式:

class 类名:
    def __init__(self, 参数, ...): # 构造函数,只在生成类的实例时被调用一次

    def 方法名1(self, 参数, ...): # 方法1

    def 方法名2(self, 参数, ...): # 方法2

# 在方法的第一个参数中明确地写入自身(自身的实例)的self是Python的一个特点

2、基于类创建对象的语法: 对象名 = 类名称( )

  • 为什么非要创建对象才能使用呢?

    • 面向对象编程类只是一种程序内的“设计图纸”,需要基于图纸生产实体(对象),才能正常工作

(二)基于类创建对象

  • 面向对象编程:设计类,基于类创建对象对象做具体的工作
  • 实例化的具体代码执行时机,是在创建对象的时候。这时候默认调用了初始化函数__init__( )
  • 我们不用显性或编写代码来调用__init__()函数,因为这个调用过程默认是静默的

四、构造方法

(一)属性(成员变量)的赋值

有没有更加高效的方式,能够一行代码就完成呢?能否像函数(方法)那样,通过传参的形式对属性赋值呢?

(二)构造方法

  • __init__( )【左右各有两个下划线_】方法,称之为构造方法

  • 可以实现:

    • 创建类对象(构造类)的时候,会自动执行/调用__init__函数

    • 创建类对象(构造类)的时候,将传入参数自动传递给__init__方法使用

  • class Student:
         name = None
         age = None
         tel = None
     ​
         def __init__(self, name, age, tel):
             self.name = name
             self.age = age
             self.tel = tel
             # 构造对象时,构造方法就会直接执行,输出语句
             print("Studnet类创建了一个类对象")
     ​
     # 执行构造方法时,会将参数传入,为类的成员变量赋值
     stu = Student("周杰伦", 12, "12345678901")
     print(stu.name)
     print(stu.age)
     print(stu.tel)
     ​
     """
     输出:
         Studnet类创建了一个类对象
         周杰伦
         12
         12345678901
     """
class Man:
    def __init__(self, name):
        self.name = name # 接收参数name,参数初始化实例变量self.name
                         # 实例变量是存储在各个实例中的变量
        print("初始化!")

    def hello(self):
        print("Hello" + self.name + "!")

    def goodbye(self):
        print("Good-bye" + self.nsmr + "!")


m = Man("David)
m.hello()
m.goodby()



"""
    初始化!
    Hello David!
    Good-bye David!
"""
  • 构造方法也是成员方法,不要忘记在参数列表中提供:self

  • 在构造方法内定义成员变量,需要使用self关键字

    • 变量是定义在构造方法内部,如果要成为成员变量,需要self表示

五、其他内置方法

  • 上文学习的__init__构造方法,是Python类内置的方法之一

(一)魔术方法

  • 这些内置的类方法,各自有各自特殊的功能,这些内置方法我们称之为:魔术方法

1、__str__字符串方法

  • 可以通过__str__方法,控制类转换为字符串的行为

  • 返回值:字符串

  • 内容:自行定义

  •  class Student:
         def __init__(self, name, age):
             self.name = name
             self.age = age
             
         def __str__(self):
             return f"Student类对象,name={self.name},age={self.age}"
             
     student = Student("周杰伦", 110)
     print(student) # 结果:student类对象,name=周杰伦,age=1
     print(str(student)) # 结果:student类对象,name=周杰伦,age=1

2、__lt__小于符号比较方法

  • 直接对2个对象进行比较是不可以的,但是在类中实现__lt__方法,即可

  • 传入参数:other另一个类对象

  • 返回值:True or Flase

  • 内容:自行定义

  • 大于:__gt__

  •  class Student:
         def __init__(self, name, age):
             self.name = name
             self.age = age
             
         def __lt__(self, other):
             return self.age < other.age
         
     stu1 = Student("周杰伦", 11)
     stu2 = Student("林俊杰", 13)
     # 比较两个对象的age,执行的是我们自定义的lt方法
     print(stu1 < stu2)  # 结果:True

3、__le__小于等于符号比较方法

  • <=、>=两种比较运算符上

  • 传入参数:other另一个类对象

  • 返回值:True or Flase

  • 内容:自行定义

  • 大于等于:__ge__

  •  class Student:
         def __init__(self, name, age):
             self.name = name
             self.age = age
             
         def __le__(self, other):
             return self.age <= other.age
         
     stu1 = Student("周杰伦", 11)
     stu2 = Student("林俊杰", 13)
     print(stu1 <= stu2) # 结果:True

4、__eq__比较运算符实现方法

  • 传入参数:other另一个类对象

  • 返回值:True or Flase

  • 内容:自行定义

  • 不实现__eq__方法,对象之间可以比较,但是默认比较内存地址

  • 不同对象==比较一定是False结果,因为两个独立的对象

  • 实现了__eq__方法,就可以按照自己的想法来决定2个对象是否相等了

  •  class Student:
         def __init__(self, name, age):
             self.name = name
             self.age = age
             
          def __eq__(self, other):
             return self.age == other.age
         
     stu1 = Student("周杰伦", 11)
     stu2 = Student("林俊杰", 11)
     print(stu1 == stu2) # 结果:True

六、封装

  • 面向对象编程,是许多编程语言都支持的一种编程思想。

  • 基于模板(类)去创建实体(对象),使用对象完成功能开发

  • 3大主要特性:

    • 封装:我们在调用一个函数或者使用一个对象时,不需要知道怎么实现这个功能,只需要知道我们应该输入什么,你会给我什么输出结果

    • 继承

    • 多态

(一)定义

  • 将现实事物的:属性、行为,封装到类中,描述为成员变量成员方法

  • 隐藏内部的变量和过程代码,仅对外暴露公开的接口

  • 这个公开的接口包括:函数名,类的方法名,需要输入的参数,会返回的数据

(二)私有成员

  • 现实世界中的事物,有属性和行为,但不代表都是开放给用户使用的

  • 既然现实事物有不公开的属性和行为,那么作为现实事物在程序中映射的类,也应该支持。

  • 私有成员变量:变量名以__开头(2个下划线)

  • 私有成员方法:方法名以__开头(2个下划线)

(三)使用私有成员

  • 私有成员无法被类对象直接使用,但是可以被其它的成员使用

  • 在类中提供仅供内部使用的属性和方法,而不对外(类对象)开放

  • 类对象只能调用公开的方法,而公开的方法内可以调用私有变量和私有方法,可以实现对私有成员和方法的访问

  • 相当于用户使用手机的某个功能,用户不需要知道了解手机内部的功能是如何运行的,手机内部会帮助用户运行调用,用户只需要使用可以使用的即可

(四)练习

 class Phone:
     # 提供私有成员变量:__is_5g_enable
     __is_5g_enable = False  # 5g状态
 ​
     def __check_5g(self):
         if self.__is_5g_enable == True:
             print("5g开启")
         else:
             print("5g关闭,使用4g网络")
 ​
     def call_by_5g(self):
         self.__check_5g()
         print("正在通话中")
 ​
 phone = Phone()
 phone.call_by_5g()

七、继承

(一)单继承

  • 继承表示:将从父类那里继承(复制)成员变量 + 成员方法(不含私有)

  •  # 演示单继承
     class Phone:
         IMEI = None # 序列号
         producer = "HM" # 厂商
         
         def call_by_4g(self):
             print("4g通话")
             
     class Phone2022(Phone):
         face_id = "10010"   # 面部识别ID
         
         def call_by_5g(self):
             print("2022新功能,5g通话")
             
     phone = Phone2022()
     phone.producer
     phone.call_by_4g()
     phone.call_by_5g()

(二)多继承

  • 一个类,可以继承多个父类

    • pass占位语句,补全函数体语法,避免报错,表示的意思就是“空”、“无内容

  • 多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)优先级

    • 先继承保留后继承被覆盖

(三)复写

  • 子类继承父类的成员属性和成员方法后,如果对其“不满意”,那么可以进行复写

  • 即:在子类中重新定义同名的属性或方法即可

    •  class Phone:
           IMEI = None # 序列号
           producer = "ITCAST" # 厂商
           
           def call_by_5g(self):
               print("父类的5G通话")
               
       class MyPhone(Phone):
           producer = "ITHEIMA"    # 复写父类属性
           
           def call_by_5g(self):   # 复写父类方法
               print("子类的5G通话")

(四)调用父类同名成员

  • 一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员

  • 需要使用被复写的父类的成员,需要特殊的调用方式:

    • 方法一:

      • 调用父类成员

      • 使用成员变量:父类名.成员变量

      • 使用成员方法:父类名.成员方法(self)     注意参数要写self

      •  class Phone:
             IMEI = None # 序列号
             producer = "ITCAST" # 厂商
             
             def call_by_5g(self):
                 print("父类的5G通话")
                 
         class MyPhone:
             producer = "ITHEIMA"    # 复写父类属性
             
             def call_by_5g(self):
                 # 方法1:调用父类成员
                 print(f"父类的品牌是:{Phone.producer}")
                 Phone.call_by_5g(self)
    • 方法二:使用super()调用父类成员

      • 使用成员变量:父类名.成员变量

      • 使用成员方法:父类名.成员方法()

      •  class Phone:
             IMEI = None # 序列号
             producer = "ITCAST" # 厂商
             
             def call_by_5g(self):
                 print("父类的5G通话")
                 
         class MyPhone:
             producer = "ITHEIMA"    # 复写父类属性
             
             # 方式2调用父类成员
             # super()相当于拿到了父类
             print(f"父类的品牌是:{super().producer}")
             super().call_by_5g()
  • 只能在子类内调用父类的同名成员

  • 子类的类对象直接调用会调用子类复写的成员

八、类型注解

  • 帮助第三方IDE工具(如PyCharm)对代码进行类型推断协助做代码提示

  • 帮助开发者自身对变量进行类型注释(备注)

  • 不会真正的对类型做验证和判断,类型注解仅仅是提示性的,不是决定性的

(一)变量的类型注解

  • 变量: 类型

  • 无法直接看出变量类型之时,会添加变量类型注解

  •  # 基础数据类型注解
     var_1: int = 10
     var_2: float = 3.1415926
     var_3: bool = True
     var_4: str = "itheima"
     var_5: Student = func()
     ​
     # 类对象类型注解
     class Student:
         pass
     #:Student表示stu变量是类对象类型,= Student()是对象创建语句
     stu: Student = Student()

(二)容器的类型注解

1、基础容器类型注解

 my_list: list = [1, 2, 3]
 my_tuple: tuple = (1, 2, 3)
 my_set: set = {1, 2, 3}
 my_dict: dict = {"itheima": 666}
 my_str: str = "itheima"

2、容器类型详细注解

 my_list: list[int] = [1, 2, 3]
 my_tuple: tuple[str, int, bool] = ("itheima", 666, True)
 my_set: set[int] = {1, 2, 3}
 my_dict: dict[str, int] = {"itheima": 666}
  • 元组类型设置类型详细注解需要将每一个元素都标记出来

  • 字典类型设置类型详细注解需要2个类型第一个是key第二个是value

(三)注释的类型注解

  • 语法:type : 类型

  •  class Student:
         pass
     ​
     var_1 = random.randint(1, 10)   # type: int
     var_2 = json.loafs(data)    # type: dict[str, int]
     var_3 = func()  # type:Studnet

(四)函数(方法)的类型注解

1、形参注解

2、返回值注解

(五)Union类型

  • 目前所掌握的注解方式:

  • 可如果遇到:数据类型无法用单一注解表示

  • 使用Union[类型, ......, 类型], 可以定义联合类型注解

  • 变量注解函数(方法)形参返回值注解,均可使用

    •  def func(data: Union[int, str]) -> Union[int, str]:
           pass

九、多态

  • 多种状态,即完成某个行为时,使用不同的对象会得到不同的状态

  • 同样的行为(函数),传入不同的对象,得到不同的状态

  • 常作用继承关系上

    • 函数(方法)形参声明接收父类对象

    • 实际传入父类的子类对象进行工作

    即:

    • 父类定义声明

    • 子类实际工作

    • 用以获得同一行为, 不同状态

(一)抽象类(接口)

  • 父类Animal的speak方法,是空实现

  • 父类用来确定有哪些方法

  • 具体的方法实现,由子类自行决定

  • 抽象类:含有抽象方法的类称之为抽象类

  • 抽象方法:方法体是空实现的(pass)称之为抽象方法

  • 抽象类就好比定义一个标准,包含了一些抽象的方法,要求子类必须实现

  • 配合多态完成:抽象的父类设计(设计标准) + 具体的子类实现(实现标准)

  • 本质上:子类继承父类,子类可以使用父类中定义成员变量成员方法

    • 都实现了制冷等,但是各自有各自的实现

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Star_KeyW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值