第六章:面向对象

本文深入探讨面向对象编程,包括类的封装、继承、多态特性,以及装饰器的概念和应用。通过实例解析了类的构造方法、私有成员、专有方法、继承与多态的实现。此外,还介绍了静态方法、类方法以及如何使用装饰器增强函数功能,包括无参装饰器、带参装饰器和类定义装饰器。装饰器在确保数据安全的同时,提供了一种灵活的代码组织方式。
摘要由CSDN通过智能技术生成

第一节:关于类

面向对象

  • 面向对象

之前我们介绍过函数,函数是对程序语句的封装与复用;
类是则是对 变量函数 的封装和复用,封装有机关联的变量和函数为类,变量和函数,称为 类的属性方法
由于类比函数的封装又提高了一个层次,因此复用性也得到进一步提升;(试想一下维护100个函数直观容易,还是维护5个类直观容易呢?)
面向过程的编程是以 函数 为核心的,而面向对象的编程是以 为核心的,一切功能的实现,都是通过创建一个司职该功能的类的实例,进而调用其方法去予以实现的;
以类为核心的、面向对象的编程,提高了代码的模块化程度,便于大规模协作的开展;
在面向对象的程序开发(Object-Oriented-Programming或OOP)中,架构师的工作,往往只是模块拆分、接口定义、实例组装,类内部的具体方法接口的实现,则交由其他人去完成;
现如今的高级语言,基本都是面向对象的;
面向对象的三大特性: 封装继承多态
另一种提法是四大特性,即三大特性的基础上,再加上一个 抽象

  • 封装

封装就是将常用的代码段封装为函数,常用的函数封装为类,常用的类封装为模块与类库;
封装提高了代码的可维护性和复用性,同时也更利于开源与传播;
封装性催生了模块化,便于大规模协作开发的开展;

  • 继承

正如自然界中,动物=>人=>程序员的关系,人是动物类的一个分支,程序员是人的一个分支,在编程中,我们可以通过继承来表达这样的关系;
动物类是人类的父类(又叫超类),人是程序员的父类;
动物类的共同特征,如都有生命、都会新陈代谢、都会死亡等等,在定义人这个类时,是无需重复声明的,这样就在一层层的继承中,节省了大量的代码;
有继承就有发展,否则继承就没有意义;

【编程中的继承】
在编程中,发展体现为:
①在父类的基础上增加新的属性与方法;
②重写(或者叫覆写、覆盖)父类方法;
对父类方法的覆写,又可以分为【颠覆式】和【改良式】两种;
【颠覆式】覆写是指子类全盘否定父类方法实现,由子类自己做一个全新的实现;
【改良式】覆写是指子类先将父类的实现拿过来,再进行新的拓展;

  • 多态

在继承的基础上,一个父类会有不同的子类实现,如战士父类可以有骑兵、步兵、弓弩手等不同子类;
多态,即【一个父类可以有多种不同的子类形态】;

【多态的共性与个性】
在多态中,同源子类之间,既存在共性,又存在个性,共性与个性各有其用处;
例如骑兵、步兵、弓弩手都是战士的子类,因此他们都有进攻方法与防守方法,这就是【共性】;
而他们的具体进攻方法各自有不同的实现,骑兵冲锋、步兵肉搏、弓弩手射箭,这就是【个性】;
在一支由不同兵种组成的军队中(即战士实例的集合),当总司令下达全体进攻的命令时,不同兵种做何种具体形式的进攻(个性)是不重要的,重要的是共性;
当司令想要采用一些细腻的战术时,比如先进行一轮齐射,再由骑兵进行一轮踩踏,最后上步兵打扫战场,此时不同兵种的差异化进攻方式则展现其价值,此时个性变得重要;
共性是由父类所带来的,个性是由子类覆写所带来的;

  • 抽象

在继承和多态中,如果父类不对某个方法做任何实现,只是留白,具体的实现交由子类自己去完成,这时我们称该方法是抽象的;
如果一个父类中的所有方法都是抽象的,我们就称该类为一个【接口】;
抽象是一种艺术,架构师就是这种艺术的玩弄者;
架构师所做的工作,就是拆分模块,定义接口,完成预组装,形成一具没有血肉的架,然后将填充的工作下放到团队中的不同程序员,填充完成之日即是项目大厦落成之时;

类的封装

例:

  • 封装一个人的类Person,需求如下:

    1、封装以下属性:姓名、年龄、存款
    2、封装自我介绍方法,陈述以上属性
    3、创建一个人,设置其基本信息
    4、打印此人信息
    5、令此人进行自我介绍

# 封装一个Person类,将与人有关的属性、方法组合在一起,以便将来复用
class Person:
    # 属性定义和默认值
    name = "林阿华"
    age = 20
    rmb = 50

    # 构造方法:外界创建类的实例时会调用
    # 构造方法是初始化实例属性的最佳时机
    def __init__(self,name,age,rmb):
        print("__init__的方法被调用了")
        self.name = name
        self.age = age
        self.rmb = rmb

    # 自我介绍方法
    #  self = 类的实例
    def tell(self):
        print("我是%s,我%d岁了,我有存款%.2f万元"%(self.name,self.age,self.rmb))
  • 创建实例p,并调用Person的tell()方法
# 创建Person类的实例
p = Person("易阿天",60,500)

# 调用实例的tell方法
p.tell()

执行结果:
在这里插入图片描述

注意将Person的属性和方法使用一个 标准制表符 缩进在Person的类定义以内;
“_ init _” 是类的构造方法,用于创建类的实例,左右各有两个下划线;
使用PyCharm输入完def __init时系统弹出提示,IDE会自动完成方法的定义;
每个方法在定义时,系统会自动加上一个 self 参数在第一个参数位,这个参数代表将来创建的实例本身;
再调用方法时, self 是不必亲自传入的,self是系统用来标识实例本身的;
构造方法的调用形式为: Person(self以外的其它参数)

类的私有成员

【成员】就是指类的属性方法
【私有】,即不能再类的外界进行访问;
目的是为了 保障安全 ,如涉及隐私的属性、核心方法实现等;

例:

  • 封装一个人的类Person,需求如下:
    1、创建一个Person类,添加存款信息
    2、保护存款信息,将其设置为私有
    3、为存款信息添加保护,使其不能被直接访问
    4、增加设置密码功能 ·增加存款查询功能
    5、只有输入密码正确的情况下才能查询存款信息
class Person:
    # 普通属性与私有属性
    name = "林阿华"
    age = 20
    __rmb = 1000  #(须通过公有方法来访问)

    #  私有方法:设置存款
    def __setrmb(self,rmb):
        self.__rmb = rmb

    #  通过普通方法访问私有方法进行存款设置
    def setrmb(self,rmb):
        pwd = input("请输入设置密码:")
        if (pwd == "123456"):
            self.__setrmb(rmb)
        else:
            print("您没有权限")

    #  公开一个普通方法,共外界访问私有属性self.__rmb
    def getrmb(self):
        pwd = input("请输入查询密码:")
        if (pwd == "123456"):
            return self.__rmb
        else:
            return "您没有访问权限"

    #  普通方法
    def tell(self):
        print("大家好,我是%s"%(self.name))
  • 创建Person实例,并通过公有方法访问私有成员
p = Person()

#通过实例访问类的普通属性
print(p.name)
print(p.age)

# 私有成员不能被直接访问
#  print(p.__rmb)        # AttributeError: 'Person' object has no attribute '__rmb'


#通过实例访问类的普通方法
p.tell()

#通过普通方法访问私有属性
rmb = p.getrmb()
print("我的存款是:",rmb)

# 通过普通方法访问私有方法
p.setrmb(500)
rmb = p.getrmb()
print("我的存款是:",rmb)

执行结果:
在这里插入图片描述- 注意的几个问题
1、代码中的__rmb属性、__setrmb方法都是私有的,在类的外部是无法p.__rmb进行直接访问的;
2、任何前置两个下划线的成员(属性与方法)都是私有的,只能在类的内部进行访问;
外界访问私有成员的方法是,使用公有方法对外界提供私有成员访问接口,但在内部先行进行权限校验,如输入密码等,如本例中的setrmb方法和getrmb方法;

类的专有方法

  • 概述

当类没有继承于任何类时,它默认继承的是 【系统的object】
在object类中,定义了许多专有方法,它们的方法名是这样的:_ xxx _,左右各有两个下划线;
专有方法不是用来给实例直接调用的,而是有其特定的用途,比如_ init _是在外界调用类名创建实例时调用的;
再比如,当外界print(obj)时,其输出的字符串其实是来源于obj对应的类的_ str _方法的返回值的;

  • 常见专有方法

    ___init___ : 构造函数,在生成对象时调用
    ___del___ : 析构函数,释放对象时使用
    ___str___:实例的打印样式
    ___len___: 获得长度
    ___ gt___: 比较大小(对象之间进行算术运算后,应返回一个计算后的结果)
    ___add___: 加运算
    ___sub___: 减运算
    ___mul___: 乘运算
    ___mod___: 求余运算
    ___pow___: 乘方

例:封装一个更加标准化的Person,需求如下:
在创建对象时打印日志
在对象销毁时打印日志
自定义对象的打印样式
设法统计人的“长度”

# 封装一个Person类,将与人有关的属性、方法组合在一起,以便将来复用

class Person:
    # 初始默认的属性
    name = "某某某"
    age = 0
    rmb = 0

    # 构造方法:外界创建类的实例时调用 ,构造方法是初始化实例属性的最佳时机
    def __init__(self, name, age, rmb):
        print("__init__:我被创建了")
        self.name = name
        self.age = age
        self.rmb = rmb

    # 析构方法,在对象被删除时调用
    def __del__(self):
        print("__del__:我被删除了")

    # 在对象被打印时,提供一个供打印的字符串
    def __str__(self):
        return "{name:%s;age:%d;rmb:%.2f}" % (self.name, self.age, self.rmb)

    # 返回对象的长度,如何计算长度是自定义的
    def __len__(self):
        return int(self.rmb)

    # 比较当前实例是否大于另一个同类的other实例,比较方法自定义
    def __gt__(self, other):
        if self.rmb > other.rmb:
            return True
        else:
            return False

    # 定义与另一个实例相加的结果
    def __add__(self, other):
        return Person(self.name + "-" + other.name, min(self.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值