python -【八】面向对象

一、类

类的定于语法:

class 类名称:

类属性(字段)

类行为(函数)

创建类对象的语法:

对象 = 类名称()

python 复制代码
"""
学生类
"""
import json


# 定义一个学生类
class Student:
    name = None  			# 姓名
    gender = None  			# 性别
    nationality = None  	# 国籍
    native_place = None  	# 籍贯
    age = None  			# 年龄


# 创建一个对象
stu = Student()
stu.name = '张三'
stu.gender = '男'
stu.nationality = '中国'
stu.native_place = '北京'
stu.age = 30

# 获取对象内的信息
stu_str = json.dumps(stu.__dict__, ensure_ascii=False)
print(stu_str)

1.1 类的成员方法

python 复制代码
class Student:
    name = None  			# 姓名
    gender = None  			# 性别
    nationality = None  	# 国籍
    native_place = None  	# 籍贯
    age = None  			# 年龄

    # 无参方法
    def say_hi(self):
        print(f'Hi, 我是{self.name}')

    # 有参方法
    def say(self, msg):
        print(f'大家好,我叫{self.name},{msg}')
        

stu = Student()
stu.name = '坤坤'
stu.gender = '男'
stu.nationality = '中国'
stu.native_place = '北京'
stu.age = 30
# 调用类方法
stu.say_hi()
stu.say('我喜欢,唱,跳,rap,篮球')

1.2 构造方法

类的构造方法作用:

  1. 创建类对象的时候,构造方法会自动执行
  2. 创建类对象的时候,将传入参数自动传递给 __init__ 方法使用
python 复制代码
class Student:
    # 构造函数内声明成员变量,不需要再定义成员变量
    def __init__(self, name, age, tel):
        self.name = name
        self.age = age
        self.tel = tel

    def print_info(self):
        print(f'姓名:{self.name}, 年龄:{self.age},电话:{self.tel}')


s = Student('张三', 19, '12345678910')
s.print_info()
s1 = Student('李四', 22, '12345678911')
s1.print_info()

1.3 练习题

开学了有一批学生信息需要录入系统,请设计一个类,记录学生的:姓名、年龄、地址,这3类信息

请实现:

  • 通过for循环,配合input输入语句,并使用构造方法,完成学生信息的键盘录入
  • 使用print语句,完成信息的输出
python 复制代码
class Stud:

    def __init__(self, idx, name, age, address):
        self.idx = idx
        self.name = name
        self.age = age
        self.address = address

    # 打印学生的信息
    def print_info(self):
        print(f'学生信息{self.idx}录入完成,信息为【姓名:{self.name},'
              f' 年龄:{self.age},地址:{self.address}】')


# 输入学生的信息
def trigger():
    for i in range(1, 3):
        name = input('请输入学生姓名:')
        age = input('请输入学生年龄:')
        address = input('请输入学生地址:')
        stud = Stud(i, name, age, address)
        stud.print_info()


if __name__ == '__main__':
    trigger()

1.4 魔术方法(内置方法)

上文中 __init__ 方法就是 python 内置方法之一,这些内置方法各自有各自的特殊功能,统称为:魔术方法

  • __init__ 构造方法
  • __str__ 字符串方法
  • __lt__ 小于,大于符号比较
  • __le__ 小于等于,大于等于符号比较
  • __eq__ == 比较符号
python 复制代码
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 对象的 tostring 方法
    def __str__(self):
        return f'对象to string, name:{self.name}, age:{self.age}'

    # 比较函数定义
    def __lt__(self, other):
        return self.age < other.age

    # 小于等于
    def __le__(self, other):
        return self.age <= other.age

    # equals 方法,不实现则是比较内存地址
    def __eq__(self, other):
        return (self.name == other.name
                and self.age == other.age)


st1 = Student('张三', 32)
print(f"对象1:{st1}")					# 对象1:对象to string, name:张三, age:32

st2 = Student('张三', 32)
print(f"对象2:{st2}")					# 对象2:对象to string, name:张三, age:32

print(f'st1 < st2: {st1 < st2}')	  	# st1 < st2: False
print(f'st1 <= st2: {st1 <= st2}')    	# st1 <= st2: True
print(f'st1 == st2: {st1 == st2}')    	# st1 == st2: True

二、面向对象的三大特性

2.1 封装

封装:将现实世界事物在类中描述为属性和方法,即为封装

私有的变量,方法定义规则:__ 两个下划线开头的定义为私有的

python 复制代码
"""
演示私有变量和私有方法的访问限制
"""

class Phone:
    # 私有成员
    __current_voltage = None

    # 私有方法
    def __keep_single_core(self):
        a = self.__current_voltage
        print(f'CPU以单核运行, 当前电压:{a}...')


p = Phone()
# 这里调用对象的私有方法会报错
# 'Phone' object has no attribute '__keep_single_core'. Did you mean: '_Phone__keep_single_core'?
p.__keep_single_core()
python 复制代码
"""
私有变量和私有方法的正确访问姿势
私有的函数并非是不能使用,而是在 class 外部不能使用,但是在 class 内部可以被使用

如下案例中:call_by_5g 函数调用了私有方法 __keep_single_core,实现了在 class 内部调用
"""

class Phone:
    __current_voltage = 0.5

    def __init__(self, cv):
        self.__current_voltage = cv

    def __keep_single_core(self):
        a = self.__current_voltage
        print(f'CPU以单核运行, 当前电压:{a}...')

    def call_by_5g(self):
        if self.__current_voltage > 3.5:
            print('5g通话开启')
        else:
            self.__keep_single_core()
            print('电压不足,无法开启5g,并使用单核运行 ...')


p = Phone(3)
p.call_by_5g()

综合案例

设计一个手机类,内部包含:

私有成员变量: __is_5g_enable,类型 boolTrue 表示开启 5gFalse 表示关闭 5g

私有成员方法: __check_5g() ,会判断私有成员 __is_5g_enable 的值

  • 若为True,打印输出: 5g开启
  • 若为False,打印输出: 5g关闭,使用4g网络

公开成员方法: call_by_5g(),调用它会执行

  • 调用私有成员方法: __check_5g(),判断 5g 网络状态
  • 打印输出: 正在通话中

运行结果:

  • 5g关闭,使用4g网络
  • 正在通话中
python 复制代码
class Phone:
    # True表示开启5g,False表示关闭5g
    __is_5g_enable = None

    def __init__(self, enable):
        self.__is_5g_enable = enable

    def __check_5g(self):
        if self.__is_5g_enable:
            print('5g开启')
        else:
            print('5g关闭,使用4g网络')

    def call_by_5g(self):
        self.__check_5g()
        print('正在通话中')


p = Phone(False)
p.call_by_5g()

2.2 继承

单继承

语法:class 类名(父类名):

python 复制代码
# Phone2021 2021年的手机,只支持 4g 通话
class Phone2021:
    IMEI = None
    product = None

    def __init__(self, IMEI, product):
        self.IMEI = IMEI
        self.product = product

    def call_by_4g(self):
        print(f'Phone2021 4g 通话, {self.IMEI}')


# 单继承
# Phone2022 2022年的手机,继承了2021年的手机
# 新增了人脸识别 和 5g 通话
class Phone2022(Phone2021):
    face_id = True

    def __init__(self, face_id, IMEI, product):
        super().__init__(IMEI, product)
        self.face_id = face_id

    def call_by_5g(self):
        print(f'Phone2022 支持 5g 通话:{self.face_id}')


p = Phone2022(face_id='zyred', IMEI='AKJL23KHH2', product='苹果')
p.call_by_4g()
p.call_by_5g()

多继承

语法:class 类名(父类名1,父类名2, ...):

python 复制代码
class Phone:
 IMEI = '100000'
 producer = None

 def __init__(self, IMEI, producer):
     self.IMEI = IMEI
     self.producer = producer

 def call(self):
     print(f'{self.producer}: 开始打电话')


class NFC:
 nfc_type = '第五代'
 producer = 'GM'

 def read_card(self):
     print(f'{self.nfc_type} 读卡')

 def write_card(self):
     print(f'{self.nfc_type} 写卡')


class RemoteControl:
 rc_type = '红外遥控'

 def control(self):
     print(f'{self.rc_type} 开启')


class MyPhone(Phone, NFC, RemoteControl):
 # 补全语法,不发生错误
 pass


mf = MyPhone('100000', '苹果')
mf.control()
mf.call()
mf.read_card()
mf.write_card()

# 多继承相同属性名,那个类继承在前面,哪个的优先级高
print(f'多继承相同属性名的内容:{mf.producer}') # 输出 "苹果"

重写父类的方法和成员属性

python 复制代码
class Phone:
    IMEI = '100000'
    producer = '苹果'

    def call(self):
        print(f'{self.IMEI}: 开始打电话')


class MyPhone(Phone):
    # 重写父类的属性
    producer = '华为'

    # 重写父类的 call 方法
    def call(self):
        print(f'开启单核CPU工作 ...')
        print(f'访问父类的属性:{Phone.producer}')
        # 调用父类的方法,方式1
        Phone.call(self)
        # 调用父类的方法,方式2
        super().call()
        print(f'关闭单核CPU工作 ...')


mf = MyPhone()
mf.call()


"""
开启单核CPU工作 ...
访问父类的属性:苹果
100000: 开始打电话
100000: 开始打电话
关闭单核CPU工作 ...
"""

2.3 多态

父类引用指向子类对象

python 复制代码
class Animal:
    # 定义一个没有任何实现的方法
    def speak(self):
        pass


class Cat(Animal):
    def speak(self):
        print('喵喵喵')


class Dog(Animal):
    def speak(self):
        print('汪汪汪')


# 定义一个方法,传入 Animal 抽象类
# 并且调用 animal 的抽象方法
def make_nise(animal: Animal):
    animal.speak()


d: Animal = Dog()
c: Animal = Cat()

make_nise(d)
make_nise(c)
python 复制代码
class AC:
    def cool_wind(self):
        """制冷"""
        pass

    def hot_wind(self):
        """制热"""
        pass

    def swing_l_r(self):
        """左右摆风"""
        pass


# 美的空调
class Midea_AC(AC):
    def cool_wind(self):
        print('美的,制冷就是爽')

    def hot_wind(self):
        print('美的,制热就是快')

    def swing_l_r(self):
        print('美的,左右无感摆风')


# 格力空调
class GREE_AC(AC):
    def cool_wind(self):
        print('格力,制冷就是爽')

    def hot_wind(self):
        print('格力,制热就是快')

    def swing_l_r(self):
        print('格力,左右无感摆风')


def make_cool(ac: AC):
    ac.cool_wind()
    ac.hot_wind()
    ac.swing_l_r()


midea: AC = Midea_AC()
gree: AC = GREE_AC()

make_cool(midea)
make_cool(gree)

"""
美的,制冷就是爽
美的,制热就是快
美的,左右无感摆风
格力,制冷就是爽
格力,制热就是快
格力,左右无感摆风
"""
相关推荐
马剑威(威哥爱编程)28 分钟前
分布式Python计算服务MaxFrame使用心得
开发语言·分布式·python·阿里云
翱翔-蓝天32 分钟前
Python知识图谱框架
开发语言·python·知识图谱
CodeMartain35 分钟前
stream流的toMap
java·开发语言
lsx20240639 分钟前
Lua 函数
开发语言
ling1s1 小时前
C#核心(18)面向对象多态vob
java·开发语言·c#
IT 古月方源1 小时前
ensp 关于ARRP 的讲解 配置
运维·开发语言·网络·tcp/ip·智能路由器
西猫雷婶2 小时前
python学opencv|读取图像(二十二)使用cv2.polylines()绘制多边形
开发语言·python·opencv
温轻舟2 小时前
前端开发 -- 自定义鼠标指针样式
开发语言·前端·javascript·css·html·温轻舟
m0_693809382 小时前
Python——day09
python·学习
xiaocaibao7772 小时前
编程语言的软件工程
开发语言·后端·golang