【Python】面向对象(一)

152 阅读7分钟

有点抽象,其实是一种编程思想。

说到面向对象,不得不提面向过程;

面向过程与面向对象:

面向过程:

根据业务逻辑从上到下的写代码实现功能,聚合性较高。

面向对象:

将数据与函数绑定在一起,进行封装,减少重复代码的重写过程,耦合度较高,更加灵活便捷

举个例子:
把大象放进冰箱:

面向过程是这样的:

  1. 打开冰箱门
  2. 把大象塞进去
  3. 关上冰箱门

面向过程编程就是分析出解决问题所需要步骤,然后分别实现每一步,再一步步执行即可。

面向对象是这样的:

这里要先搞清楚,面向对象是什么?搞清楚啥是对象?

万物皆对象:比如,我们把冰箱视为一个对象,那么它是由什么组成的呢?又可以用来干什么?

image.png

因此:对象 = 属性 + 行为

下面,我们用面向对象,来实现把大象放进冰箱:

  1. 调用:冰箱 -> 打开门(行为)
  2. 调用:冰箱 -> 装东西(行为)
  3. 调用:冰箱 -> 关闭门(行为)

看起来和面向过程没啥区别,但我们的思想发生了重大的转变,我们把冰箱当作了一个独立的对象,我们是通过和冰箱这个对象交互完成了整个过程。

重点在于:如果我们有时候需要对某个对象,进行增删改,单独对其进行操作则使用面向对象更方便;而面向过程改动前一个就会影响后一个,发生一连串的连锁反应。

但并不是说面向对象有多好,面向过程有多么不好,是想说:我们可以根据具体的场景,来决定采用哪个编程方式或思想。

类:

用来描述具有相同属性和方法的对象的集合,

比如:“人”是一个类,“植物”是一个类...

对象:

某一个具体事物的存在 ,在现实世界中可以是看得见摸得着的,

比如:“胡歌”是一个对象

在开发中,是先有类,再有对象。

类与对象的关系:

  • 类是对象的抽象
  • 对象是类的实例

我们可以进行对象归类: 举例:分析班级同学共有的特征,进行归类:

image.png

然后,还可以对学生公有的特征进行归类,从而建立一个学生类:

image.png

练习:

下面哪些是类?哪些是对象?

  • 汽车
  • 奔驰、宝马、五菱、红旗、几何...
  • 水果
  • 香蕉、苹果、橘子、奇异果、芒果...

类的构成:

类由3个部分构成:

  • 类的名称:类名
  • 类的属性:一组数据
  • 类的方法:允许对类进行操作的方法

注意:类名通常采用驼峰式命名方式,尽量让字面意思体现出类的作用。

类的定义:

Python使用class关键字来定义类,其基本结构如下:

class 类名pass

如何创建对象:

Python中,可以根据已经定义的类去创建出一个个对象 创建对象的格式为:

对象名 = 类名()
练习:
  1. 创建类:学生类
  2. 创建对象:张三
  3. 在类中定义方法输出:张三学习Python

image.png

class Students:  # 创建一个类
    
    # 定义一个类的方法/函数
    def study(self):  
        print('我正在学习面向对象,你呢?')


# 创建对象(实例),这个过程即是实例化对象
a = Students()

# 执行类中的方法
a.study()

self 参数:

在类当中定义方法时,会发现系统帮我们自动创建了 self 参数,并且在调用对象的该方法时,也无需传入 self 参数。那这个 self 是什么? 接下来一起先看个例子:

举例:
  • 定义类为:demo类
  • 创建对象:崔东山
  • 在类中定义方法:打印李四信息
class demo:
    def func(self):
        print(f'你好哇,我是{ls.name},我今年{ls.age}岁,很高兴认识你。')


ls = demo()
ls.name = '崔东山'
ls.age = '80'
ls.func()

通过这个例子,可以看出,对象将自身的信息在类的外部定义并赋值,封装到了类的内部。 即:self是:

  • self本身是形参
  • self就是当前对象本身

当我再想创建一个对象时并打印对应信息时,发现这样并不是很灵活,因此可以优化如下:

class demo:
    def func(self):
        print(f'你好哇,我是{self.name},我今年{self.age}岁了,很高兴认识你。')


ls = demo()
ls.name = '东山'
ls.age = '80'
ls.func()

zs = demo()
zs.name = '平安'
zs.age = '40'
zs.func()

但是这样仍然有缺陷,我们会发现,用户信息暴露在类的外部。

魔法方法( Magic methods ):

在Python的类中,以两个下划线开头、两个下划线结尾的方法,如常见的 : initstrdel等,就被称为「魔法方法」。

因为这些方法都是到达某个条件自动触发 无需调用,所以,称之为 魔法方法。

init():初始化对象_不带参数时:

在创建⼀个对象时默认被调⽤,不需要⼿动调⽤

init(self) 中的self参数,不需要开发者传递,python解释器会⾃动把当前的对象引⽤传递过去。

class my_apple:

    # 初始化
    def __init__(self):
        self.width = 10
        self.high = 20

    def main(self):
        print(self.width)
        print(self.high)


iPad = my_apple()
iPad.main()
init(),带参数时:

⼀个类可以创建多个对象, 对不同的对象设置不同的初始化属性:传参即可。

class MyMobilePhone:
    def __init__(self, size, color):
        self.size = size
        self.color = color

    def my_huawei(self):
        print(f'我的华为手机尺寸是{self.size},其机身颜色为{self.color}。')

    def my_apple(self):
        print(f'我的苹果手机尺寸是{self.size},机身的颜色是{self.color}。')


# 对不同的对象,设置不同的初始化属性
mobile_1 = MyMobilePhone(6.5, '白色')
mobile_1.my_huawei()

mobile_2 = MyMobilePhone(5.5, '紫色')
mobile_2.my_apple()
str():

当使⽤ print 输出对象的时候,默认打印对象的内存地址。类定义了 str() ⽅法后,会打印在这个⽅法中 return 的数据。 解释类的属性或作用.

class Demo_1:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def __str__(self):
        return f'这部手机的宽为:{self.width},高为:{self.height}'


a = Demo_1(10, 20)
print(a)
del():

在对象销毁时被调用,当对象不再被使用时,del()方法则运行。

class Demo_2:
    def __init__(self, color, size):
        self.color = color
        self.size = size

    def __del__(self):
        print('对象已被删除...')


b = Demo_2('天蓝色', 30)
class Demo_3:
    # 当由该类创建的实例对象,被删除或者在内存中被释放,将会自动触发并执行。
    def __del__(self):
        print('被释放了..')  # 程序执行完,最后调用


c = Demo_3()
print('-----')

类的属性与方法:

类的私有属性:

__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。

class Demo:
    __num = 0  # 私有属性,以2个下划线开头
    result = 0

    def Count(self):
        self.__num += 3
        self.result += 1
        print(f'打印私有变量的值:{self.__num}')
        print(f'打印公开属性的值:{self.result}')

    def GetNum(self):
        return self.__num


number = Demo()
number.Count()
print('在外面,直接打印公开的属性值:', number.result)
# print(number.__num)  # 报错,实例(对象)不能访问私有变量

num = number.GetNum()
print(f'当私有属性,被实例调用方法后:返回值为{num}')  # 3

类的私有方法:

class Demo_2:
    def func_1(self):
        print('这是公开的方法,随便打印个内容--111')

    # 类的私有方法
    def __func_2(self):
        print('这是私有方法,随便打印个内容--222')

    def func_3(self):
        return self.__func_2()


f = Demo_2()
f.func_1()
# f.__func_2()  # 报错:AttributeError: 'Demo_2' object has no attribute '__func_2',对象没有属性
f.func_3()

# 不建议这样使用:对象._类名__私有属性
print(f._Demo_2__func_2)  # <bound method Demo_2.__func_2 of <__main__.Demo_2 object at 0x100750b50>>

实例属性:

class Province:
    # 初始化
    def __init__(self, country, province):
        self.country = country
        self.province = province

    def PrintInfo(self):
        
        # 通过self去访问,当对象有很多个时,会方便很对
        print(f'您当前停留在{self.country},所在省份为{self.province}')

        # 通过每个对象去访问,当对象有很多个时,这样比较麻烦
        print(HuNan.country, HuNan.province)


HuNan = Province('中国', '湖南')
HuNan.PrintInfo()

zg = Province('中国', '北京')
zg.PrintInfo()

实例方法:

class Demo:
    def __init__(self):
        self.name = 'Maria'

    # 实例方法
    def func(self):
        print(self.name)


a = Demo()
a.func()

下面来个综合应用的练习:

烤地瓜:

题目分析:

涉及一个事物,地瓜,因此需要涉及到一个类:地瓜类

地瓜类的属性:

  • 被烤的时间
  • 被烤后的状态

地瓜的实例方法:

  • 可以被加热烤熟
  • 可以根据口味添加对应的调料

打印对象的信息

需求:

1、被烤的时间和地⽠对应的状态:

  • 0  -  5分钟 : ⽣的
  • 5 - 10分钟 :  半⽣不熟
  • 10-12分钟 : 烤熟了
  • 超过12分钟:   烤糊了

2、添加调料:

代码实现:

class RoastedSweetPotato:

    # 初始化
    def __init__(self):
        self.cookTime = 0
        self.cookState = '生的'
        self.cookTaste = []

    # 烤的时间
    def cook(self, time):

        # 初始值 加上 被烤的时间
        self.cookTime += time

        if 0 <= self.cookTime < 5:
            self.cookState = '当前还是生的'
        if 5 <= self.cookTime < 10:
            self.cookState = '快烤熟了'
        if 10 <= self.cookTime < 12:
            self.cookState = '已经烤熟啦'
        if self.cookTime >= 12:
            self.cookState = '哎呀,糟糕,烤糊了'

    # 添加调味料
    def addSeasoning(self, *args):
        self.cookTaste.append(args)

    # 显示地瓜状态
    def __str__(self):
        return f'这个地瓜已经烤了{self.cookTime}分钟,当前状态为{self.cookState}'


if __name__ == '__main__':
    # 创建对象
    eat = RoastedSweetPotato()

    # 调用烤的方法,传入烤的时间
    eat.cook(11)

    # 调用添加的调料,传入添加的调料
    eat.addSeasoning('辣椒面', '椒盐')

    # 打印自定义内容
    print(eat)