Python开发-027_初识面向对象

Python中支持两种编程方式来写代码,分别是:函数式编程面向对象式编程

  • 函数式

    # 定义函数,在函数中实现功能
    def func():
      res = "一个NB的功能"
      return res
    
    # 执行函数
    demo = func()
    
  • 面向对象

    # 定义类
    class Foo(object):
        # 在类中定义方法
        def func(self):
            print("一个NB的功能")
        
    # 实例化类的对象
    obj = Foo()
    # 执行类中的方法
    obj.func()
    

python支持两种编程方式(其他很多语言只支持一种),行业内对于函数式编程vs面向对象编程 之间谁更好的讨论也是难分胜负,我们不必非纠结于那种方式更好,编程语言支持工具,最重要的是把功能实现

1 快速使用面向对象

想要通过面向对象去实现某个或某功能需要以下两个步骤

class Message:
    # 函数在对象中被称为方法 def 方法名(self,....) self是固定搭配
    def send_email(self,email,content):
        data = "给{}发邮件,内容是:{}".format(email,content)
        print(data)

msg_object = Message() # 实例化一个对象 msg_object,创建了一个区域
msg_object.send_email("kinght@geekxk.com","注册成功")
  • 定义类
    • 通过class定义一个类
      • py3之后默认类都继承object
      • 类名称首字母大写&驼峰式命名(多单词每一个单词首字母大写)
    • 在类中编写一个方法
      • 在类种编写的函数称为方法
      • 方法的第一个参数必须是self
  • 使用类
    • 需要实例化一个对象
    • 通过实例化的对象调用其中的方法

类中也可以同时定义多个方法

class Message:
    def send_email(self, email, content):
        data = "给{}发邮件,内容是:{}".format(email, content)
        print(data)
    def send_wechat(self, vid, content):
        data = "给{}发微信,内容是:{}".format(vid, content)
        print(data)
msg_object = Message()
msg_object.send_email("kinght@geekxk.com", "注册成功")
msg_object.send_wechat("kinght", "注册成功")

用面向对象编程写的类有点像归类的意思:将某些相似的函数划分到一个类中,但,这种编写方式让人感觉有些鸡肋

2 对象与self

类与包有一个类似的东西,就是__init__,在类中也可以定义一个特殊的__init__ 初始化方法 ,它在实例化类创建对象对象=类()的时候会自动执行

话回路转,实例化类创建对象的时候,python会在内存中开辟一块空间存放数据,这块空间专属于独立的对象,在全局中调用这块空间中的变量对象名.变量名,而如果要在方法中使用这块空间中的变量,这种方式就会被局限,所以在方法中这块儿空间的名称被指为self,而调用变量则是self.变量名

image-20220428162453871

class Message:
    def __init__(self,content):
        self.data = content
    def send_mali(self,email):
        data = "给{}发邮件,内容是{}".format(email,self.data)
        print(data)
    def send_wchat(self,vid):
        data = "给{}发微信,内容是{}".format(vid,self.data)
        print(data)

# 实例化Message创建对象msg_object
msg_object = Message("注册成功")
print(msg_object.data) # 注册成功
msg_object.send_mali("kinght@geekxk.com") # 给kinght@geekxk.com发邮件,内容是注册成功
msg_object.send_wchat("kinght") # 给kinght发微信,内容是注册成功

# 实例化Message创建对象msg_msg_object
msg_msg_object = Message("注册失败")
print(msg_msg_object.data) # 注册失败
msg_msg_object.send_mali("kinght@geekxk.com") # 给kinght@geekxk.com发邮件,内容是注册失败
msg_msg_object.send_wchat("kinght") # 给kinght发微信,内容是注册失败

通过上述的示例,你会发现:

  • 对象,让我们可以在它的内部先封装一部分数据,以后想要使用时,再去里面获取。
  • self,类中的方法需要由这个类的对象来触发并执行对象.方法名 ,且在执行时会自动将对象当做参数传递给self,以供方法中获取对象中已封装的值。

注意:除了self默认参数以外,方法中的参数的定义和执行与函数是相同。

当然,根据类也可以创建多个对象并执行其中的方法

面向对象的思想:将一些数据封装到对象中,在执行方法时,再去对象中获取。

函数式的思想:函数内部需要的数据均通过参数的形式传递。

  • self,本质上就是一个参数。这个参数是Python内部会提供,其实本质上就是调用当前方法的那个对象。
  • 对象,基于类实例化出来”一块内存“,默认里面没有数据;经过类的 __init__方法,可以在内存中初始化一些数据。

3 常见成员

在编写面向对象相关代码时,最常见成员有:

  • 实例变量,属于对象,只能通过对象调用
  • 绑定方法,属于类,通过对象调用 或 通过类调用

注意:还有很多其他的成员,后续再来介绍

class Person:
    def __init__(self, n1, n2):
        # 实例变量
        self.name = n1
        self.age = n2
    # 绑定方法
    def show(self):
        msg = "我叫{},今年{}岁。".format(self.name, self.age)
        print(msg)

    def all_message(self):
        msg = "我是{}人,我叫{},今年{}岁。".format(Person.country, self.name, self.age)
        print(msg)

    def total_message(self):
        msg = "我是{}人,我叫{},今年{}岁。".format(self.country, self.name, self.age)
        print(msg)


p1 = Person("kinght",20) # 初始化,实例化了Person类的对象叫p1
p1.show() # 执行绑定方法

p2 = Person("QAQ",20)
Person.show(p2) # 执行绑定方法

4 应用示例

4.1 应用实例1:将注册信息封装成对象方便使用

class UserInfo:
    def __init__(self,name,pwd):
        self.name = name
        self.pwd = pwd

def run():
    user_object_list = []
    while True:
        username = input("请输入用户名(Q退出):").strip()
        if username.upper() == "Q":
            break
        passwd = input("请输入密码:").strip()
        # 将用户的注册信息封装实例化封装成对象
        user_object = UserInfo(username,passwd)
        # 将对象存储到列表中
        user_object_list.append(user_object)
    for obj in user_object_list:
        # 循环调用各个实例化对象中封装的name和pwd值
        print(obj.name,obj.pwd)
if __name__ == "__main__":
    run()

注意:用字典也可以实现做封装,只不过字典在操作值时还需要自己写key,面向对象只需要 . 即可获取对象中封装的数据

总结:
	- 数据封装到对象,以后再去获取。
    - 规范数据(约束)

4.2 应用实例2:用户翻页系统,对输入进行预处理

将数据封装到对象中,在方法中对原始数据进行加工处理

class Pagination:
    def __init__(self,current_page,per_page_num=10):
        self.per_page_num = per_page_num
        if not current_page.isdecimal():
            # 输入非整数,默认返回第一页
            self.current_page = 1
            return
        current_page = int(current_page)
        if current_page < 1:
            # 输入数字小于1,默认返回第一页
            self.current_page = 1
            return
        self.current_page = current_page
	
    # start函数和stop函数可以直接取封装的数据,不用再次传递
    def start(self):
        # 计算起始序号
        return (self.current_page-1) * self.per_page_num
    def stop(self):
        # 计算结束序号
        return self.current_page * self.per_page_num

def run():
    User_list = ["用户-{}".format(i) for i in range(1, 3000)]

    page = input("请输入页数:")
    pg_object = Pagination(page,10)
    page_data_list = User_list[pg_object.start():pg_object.stop()]
    print(page_data_list)
if __name__ == "__main__":
    run()

4.3 应用实例3:下载视频,在self中保存文件路径

import os,requests

class DouYin:
    def __init__(self,folder_path):
        '''
        获得文件保存文件夹路径,如果路径不存在则生成文件夹
        :param folder_path: 文件保存文件夹
        '''
        self.folder_path = folder_path
        if not os.path.exists(folder_path): # 判断目录是否存在
            os.makedirs(folder_path) # 创建目录
    def download(self,file_name,url):
        '''
        下载视频
        :param file_name: 视频文件名
        :param url: 下载链接
        :return: None
        '''
        res = requests.get(
            url = url,
            headers={
                "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 FS"
            }
        )
        file_path = os.path.join(self.folder_path, file_name)
        with open(file_path,mode='wb') as f:
            f.write(res.content)
            f.flush()
    def multi_download(self,video_list):
        '''
        批量下载视频
        :param video_list: 视频列表(文件名,下载链接)
        :return:None
        '''
        for item in video_list:
            self.download(item[0],item[1])

if __name__ == '__main__':
    douyin_object = DouYin("videos")

    douyin_object.download(
        "罗斯.mp4",
        "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg"
    )

    video_list = [
        ("a1.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300fc20000bvi413nedtlt5abaa8tg"),
        ("a2.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0d00fb60000bvi0ba63vni5gqts0uag"),
        ("a3.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg")
    ]
    
    # 批量下载
    douyin_object.multi_download(video_list)

4.4 实例应用4:匪徒游戏,将功能封装成模板

# 警匪游戏

class Police:
    def __init__(self,name,role):
        self.name = name
        self.role = role # 职位
        if role == "队员":
            self.hit_points = 200 # 队员200血
        else:
            self.hit_points = 500 # 队长500血

    def show_status(self):
        # 查看警察状态
        message = "警察姓名:{},当前血量:{}".format(self.name,self.hit_points)
        print(message)
    def bomb(self,terrorist_list):
        # 警方攻击方式:投掷炸弹
        for terrorits in terrorist_list:
            terrorits.blood -= 20 # 调用了匪徒血量方法
            terrorits.show_status()

class Terrorits():
    def __init__(self,name):
        self.name = name
        self.blood = 300
    def show_status(self):
        message = "匪徒姓名:{},当前血量:{}".format(self.name,self.blood)
        print(message)
    def shoot(self,police_object):
        police_object.hit_points -= 5
        police_object.show_status() # 查看警察状态
        # 后坐力
        self.blood -= 1
        self.show_status()
    def strafe(self,police_object_list):
        for police_object in police_object_list:
            police_object.hit_points -= 3
            police_object.show_status()


def run():
    # 创建三个警察
    p1 = Police("aaa",'队员')
    p2 = Police("bbb",'队员')
    p3 = Police("ccc",'队长')

    # 创建2个匪徒
    t1 = Terrorits('111')
    t2 = Terrorits('222')

    # 匪徒率先射击
    t1.shoot(p1)
    # 警察手雷还击
    p3.bomb([t1,t2])
    # 匪徒扫射
    t2.strafe([p1,p2,p3])

if __name__ == '__main__':
    run()

总结:

  • 仅做数据封装。
  • 封装数据 + 方法再对数据进行加工处理。
  • 创建同一类的数据且同类数据可以具有相同的功能(方法)

Python开发-027_初识面向对象
http://localhost:8080/archives/Duo3Jppo
作者
kinght
发布于
2024年11月11日
更新于
2024年11月11日
许可协议