最新从零学Python:第十六课-面向对象编程入门

    print(f'学生正在学习{course_name}.')

def play(self):
    print(f'学生正在玩游戏.')

#### 创建和使用对象


在我们定义好一个类之后,可以使用构造器语法来创建对象,代码如下所示。



stu1 = Student()
stu2 = Student()
print(stu1) # <main.Student object at 0x10ad5ac50>
print(stu2) # <main.Student object at 0x10ad5acd0>
print(hex(id(stu1)), hex(id(stu2))) # 0x10ad5ac50 0x10ad5acd0


在类的名字后跟上圆括号就是所谓的构造器语法,上面的代码创建了两个学生对象,一个赋值给变量stu1,一个复制给变量stu2。当我们用print函数打印stu1和stu2两个变量时,我们会看到输出了对象在内存中的地址(十六进制形式),跟我们用id函数查看对象标识获得的值是相同的。现在我们可以告诉大家,我们定义的变量其实保存的是一个对象在内存中的逻辑地址(位置),通过这个逻辑地址,我们就可以在内存中找到这个对象。所以stu3 = stu2这样的赋值语句并没有创建新的对象,只是用一个新的变量保存了已有对象的地址。


接下来,我们尝试给对象发消息,即调用对象的方法。刚才的Student类中我们定义了study和play两个方法,两个方法的第一个参数self代表了接收消息的学生对象,study方法的第二个参数是学习的课程名称。Python中,给对象发消息有两种方式,请看下面的代码。



通过“类.方法”调用方法,第一个参数是接收消息的对象,第二个参数是学习的课程名称

Student.study(stu1, ‘Python程序设计’) # 学生正在学习Python程序设计.

通过“对象.方法”调用方法,点前面的对象就是接收消息的对象,只需要传入第二个参数

stu1.study(‘Python程序设计’) # 学生正在学习Python程序设计.

Student.play(stu2) # 学生正在玩游戏.
stu2.play() # 学生正在玩游戏.


#### 初始化方法


大家可能已经注意到了,刚才我们创建的学生对象只有行为没有属性,如果要给学生对象定义属性,我们可以修改Student类,为其添加一个名为\_\_init\_\_的方法。在我们调用Student类的构造器创建对象时,首先会在内存中获得保存学生对象所需的内存空间,然后通过自动执行\_\_init\_\_方法,完成对内存的初始化操作,也就是把数据放到内存空间中。所以我们可以通过给Student类添加\_\_init\_\_方法的方式为学生对象指定属性,同时完成对属性赋初始值的操作,正因如此,\_\_init\_\_方法通常也被称为初始化方法。


我们对上面的Student类稍作修改,给学生对象添加name(姓名)和age(年龄)两个属性。



class Student:
“”“学生”“”

def __init__(self, name, age):
    """初始化方法"""
    self.name = name
    self.age = age

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

def play(self):
    """玩耍"""
    print(f'{self.name}正在玩游戏.')

修改刚才创建对象和给对象发消息的代码,重新执行一次,看看程序的执行结果有什么变化。



由于初始化方法除了self之外还有两个参数

所以调用Student类的构造器创建对象时要传入这两个参数

stu1 = Student(‘骆昊’, 40)
stu2 = Student(‘王大锤’, 15)
stu1.study(‘Python程序设计’) # 骆昊正在学习Python程序设计.
stu2.play() # 王大锤正在玩游戏.


#### 打印对象


上面我们通过\_\_init\_\_方法在创建对象时为对象绑定了属性并赋予了初始值。在Python中,以两个下划线\_\_(读作“dunder”)开头和结尾的方法通常都是有特殊用途和意义的方法,我们一般称之为**魔术方法**或**魔法方法**。如果我们在打印对象的时候不希望看到对象的地址而是看到我们自定义的信息,可以通过在类中放置\_\_repr\_\_魔术方法来做到,该方法返回的字符串就是用print函数打印对象的时候会显示的内容,代码如下所示。



class Student:
“”“学生”“”

def __init__(self, name, age):
    """初始化方法"""
    self.name = name
    self.age = age

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

def play(self):
    """玩耍"""
    print(f'{self.name}正在玩游戏.')

def __repr__(self):
    return f'{self.name}: {self.age}'

stu1 = Student(‘骆昊’, 40)
print(stu1) # 骆昊: 40
students = [stu1, Student(‘王小锤’, 16), Student(‘王大锤’, 25)]
print(students) # [骆昊: 40, 王小锤: 16, 王大锤: 25]


#### 面向对象的支柱


面向对象编程有三大支柱,就是我们之前给大家划重点的时候圈出的三个词:封装、继承和多态。后面两个概念在下一节课中会详细说明,这里我们先说一下什么是封装。我自己对封装的理解是:**隐藏一切可以隐藏的实现细节,只向外界暴露简单的调用接口**。我们在类中定义的对象方法其实就是一种封装,这种封装可以让我们在创建对象之后,只需要给对象发送一个消息就可以执行方法中的代码,也就是说我们在只知道方法的名字和参数(方法的外部视图),不知道方法内部实现细节(方法的内部视图)的情况下就完成了对方法的使用。


举一个例子,假如要控制一个机器人帮我倒杯水,如果不使用面向对象编程,不做任何的封装,那么就需要向这个机器人发出一系列的指令,如站起来、向左转、向前走5步、拿起面前的水杯、向后转、向前走10步、弯腰、放下水杯、按下出水按钮、等待10秒、松开出水按钮、拿起水杯、向右转、向前走5步、放下水杯等,才能完成这个简单的操作,想想都觉得麻烦。按照面向对象编程的思想,我们可以将倒水的操作封装到机器人的一个方法中,当需要机器人帮我们倒水的时候,只需要向机器人对象发出倒水的消息就可以了,这样做不是更好吗?


在很多场景下,面向对象编程其实就是一个三步走的问题。第一步定义类,第二步创建对象,第三步给对象发消息。当然,有的时候我们是不需要第一步的,因为我们想用的类可能已经存在了。之前我们说过,Python内置的list、set、dict其实都不是函数而是类,如果要创建列表、集合、字典对象,我们就不用自定义类了。当然,有的类并不是Python标准库中直接提供的,它可能来自于第三方的代码,如何安装和使用三方代码在后续课程中会进行讨论。在某些特殊的场景中,我们会用到名为“内置对象”的对象,所谓“内置对象”就是说上面三步走的第一步和第二步都不需要了,因为类已经存在而且对象已然创建过了,直接向对象发消息就可以了,这也就是我们常说的“开箱即用”。


#### 经典案例


#### 例子1:定义一个类描述数字时钟。



import time

定义数字时钟类

class Clock(object):
“”“数字时钟”“”

def __init__(self, hour=0, minute=0, second=0):
    """初始化方法
    :param hour: 时
    :param minute: 分
    :param second: 秒
    """
    self.hour = hour
    self.min = minute
    self.sec = second

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

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

创建时钟对象

clock = Clock(23, 59, 58)
while True:
# 给时钟对象发消息读取时间

还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!

王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。

对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!

【完整版领取方式在文末!!】

93道网络安全面试题

内容实在太多,不一一截图了

黑客学习资源推荐

最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

1️⃣零基础入门
① 学习路线

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

image

② 路线对应学习视频

同时每个成长路线对应的板块都有配套的视频提供:

image-20231025112050764

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 18
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值