Python学习的第十八天:面向对象的程序设计

Python学习的第十八天:面向对象的程序设计

对面向对象编程的基础理解

  • 指令式编程 —> 面向过程(函数)编程 —> 程序比较简单的时候没有任何毛病

  • 编程范式(程序设计的方法论):面向对象编程 / 函数式编程

  • 对象:对象是可以接收消息的实体,面向对象编程就是通过给对象发消息达到解决问题的目标。

  • 对象 = 数据 + 函数(方法)—> 对象将数据和操作数据的函数从逻辑上变成了一个整体。

    • 一切皆为对象
    • 对象都有属性和行为
    • 每个对象都是独一无二的
    • 对象一定属于某个类
  • 类:将有共同特征(静态特征和动态特征)的对象的共同特征抽取出来之后得到的一个抽象概念。

  • 简单的说,类是对象的蓝图(模板),有了类才能够创建出这种类型的对象。

  • 面向对象编程:

    1. 定义类 —> 类的命名使用驼峰命名法(每个单词首字母大写)

      • 数据抽象:找到和对象相关的静态特征(属性)—> 找名词
      • 行为抽象:找到和对象相关的动态特征(方法)—> 找动词
    2. 造对象

    3. 发消息

例子1:面向对象编程的构建方法
# 第一步:定义类
class Student:
    """学生"""

    # 数据抽象(属性)
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 行为抽象(方法)
    def eat(self):
        """吃饭"""
        print(f'{self.name}正在吃饭.')

    def study(self, course_name):
        """学习"""
        print(f'{self.name}正在学习{course_name}.')

    def play(self, game_name):
        """玩"""
        print(f'{self.name}正在玩{game_name}.')

    def daily(self):
        """日常"""
        if self.age < 22:
            print(f'{self.name}正在上学')
        else:
            print(f'{self.name}正在工作')
       
    # 第二步:创建对象 ---> 构造器语法 ---> 类名(..., ...)
    stu1 = Student('小明', 15)
    stu2 = Student('小红', 41)

    # 第三步:给对象发消息(调用对象的方法)
    stu1.study('Python程序设计')
    stu1.eat()
    stu1.daily()

    stu2.play('斗地主')
    stu2.daily()
	
    # 可以直接更改数据
    stu1.age = 23
    stu1.daily()

在这里插入图片描述

例子2:电子表的运作
import os
import time


class Clock:
    """时钟"""

    def __init__(self, hour=0, minute=0, second=0):
        self.hour = hour
        self.minute = minute
        self.second = second

    def show(self):
        """显示时间"""
        return f'{self.hour:0>2d}:{self.minute:0>2d}:{self.second:0>2d}'

    def run(self):
        """走字"""
        self.second += 1
        if self.second == 60:
            self.second = 0
            self.minute += 1
            if self.minute == 60:
                self.minute = 0
                self.hour += 1
                if self.hour == 24:
                    self.hour = 0


if __name__ == '__main__':
    clock = Clock(23, 59, 58)
    while True:
        os.system('clear')
        print(clock.show())
        time.sleep(1)
        clock.run()

特殊技巧

  1. 我们在类里面写的函数,通常称之为方法,它们基本上都是发给对象的消息。但是有的时候,我们的消息并不想发给对象,而是希望发给这个类(类本身也是一个对象),这个时候,我们可以使用静态方法或类方法:

    静态方法 - 发给类的消息 —> @staticmethod —> 装饰器
    类方法 - 发给类的消息 —> @classmethod —> 装饰器 —> 第一个参数(cls)是接收消息的类

    例子:定义描述三角形的类,提供计算周长和面积的方法

    class Triangle:
        """三角形"""
    
        def __init__(self, a, b, c):
            self.a = a
            self.b = b
            self.c = c
    
        # @classmethod
        # def is_valid(cls, a, b, c):
        #     return a + b > c and b + c > a and a + c > b
    
        @staticmethod
        def is_valid(a, b, c):
            return a + b > c and b + c > a and a + c > b
    
        def perimeter(self):
            return self.a + self.b + self.c
    
        def area(self):
            half = self.perimeter() / 2
            return (half * (half - self.a) * (half - self.b) * (half - self.c)) ** 0.5
    
    
    if __name__ == '__main__':
        # 调用静态方法,判断三条边能否构成三角形
        if Triangle.is_valid(3, 4, 5):
            t = Triangle(3, 4, 5)
            print(t.perimeter())
            print(t.area())
        else:
            print('无效的边长,无法构造三角形对象')
    

在这里插入图片描述

  1. 魔术方法(魔法方法)—> 有特殊用途和意义的方法
    init —> 初始化方法,在调用构造器语法创建对象的时候会被自动调用
    str —> 获得对象的字符串表示,在调用print函数输出对象时会被自动调用
    repr —> 获得对象的字符串表示,把对象放到容器中调用print输出时会自动调用
    —> representation
    lt —> 在使用 < 运算符比较两个对象大小时会自动调用
    1. 如果一个变量的取值只有有限个选项,可以考虑使用枚举类型。
      Python中没有定义枚举类型的语法,但是可以通过继承Enum类来实现枚举类型。
      结论1:枚举类型是定义符号常量的最佳选择
      结论2:符号常量(有意义的名字)总是优于字面常量

    例子:扑克游戏,四个玩家参与,先洗牌,再把牌发到四个玩家的手上。

from enum import Enum
import random


# 枚举类型
class Suite(Enum):
    SPADE, HEART, CLUB, DIAMOND = range(4)


class Card:
    """牌"""

    def __init__(self, suite, face):
        self.suite = suite
        self.face = face

    def __str__(self):
        return self.show()

    def __repr__(self):
        return self.show()

    def __lt__(self, other):
        if self.suite == other.suite:
            return self.face < other.face
        return self.suite.value < other.suite.value

    def show(self):
        """显示"""
        suites = ['♠️', '❤️', '♣️', '♦️']
        faces = ['', 'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
        return f'{suites[self.suite.value]}{faces[self.face]}'


class Poker:
    """扑克"""

    def __init__(self):
        self.cards = [Card(suite, face)
                      for suite in Suite
                      for face in range(1, 14)]
        self.counter = 0

    def shuffle(self):
        """洗牌"""
        self.counter = 0
        random.shuffle(self.cards)

    def deal(self) -> Card:
        """发牌"""
        card = self.cards[self.counter]
        self.counter += 1
        return card

    def has_more(self) -> bool:
        """是否还有牌"""
        return self.counter < len(self.cards)

    
class Player:
    """玩家"""

    def __init__(self, nickname):
        self.nickname = nickname
        self.cards = []

    def get_one_card(self, card):
        """摸一张牌"""
        self.cards.append(card)

    def arrange(self):
        """整理手上的牌"""
        self.cards.sort()

    def show(self):
        """显示玩家手上的牌"""
        print(self.nickname, end=': ')
        for card in self.cards:
            print(card, end=' ')
        print()


def main():
    nicknames = ('小明', '小红', '小亮', '小李')
    players = [Player(nickname) for nickname in nicknames]
    poker = Poker()
    poker.shuffle()
    # 将牌发到四个玩家的手上
    for _ in range(13):
        for player in players:
            card = poker.deal()
            player.get_one_card(card)
    # 显示四个玩家手上的牌
    for player in players:
        player.arrange()
        player.show()


if __name__ == '__main__':
    main()

在这里插入图片描述
)]

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

踏墟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值