Day08.面向对象编程基础

Python实战教程100天:Day08-面向对象编程基础 Python实战教程 面向对象编程基础 活在当下的程序员应该都听过“面向对象编程”一词,也经常有人问能不能用一句话解释下什么是“面向对象编程”,我们先来看看比较正式的说法。 把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的特化(specializatio... 阅读详情

面向对象编程基础



前言

活在当下的程序员应该都听过"面向对象编程"一词,也经常有人问能不能用一句话解释下什么是"面向对象编程",我们先来看看比较正式的说法。

"把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的特化(specialization)和泛化(generalization),通过多态(polymorphism)实现基于对象类型的动态分派。"

个人理解为:面向对象思想主要是三大要素:封装,继承和多态。

  • 封装:就是将某个“对象”包装起来,反正就是别人不知道你里面(运行过程中)发生了什么,除非你自己特地告诉别人。
  • 继承:就是可以从你的父辈(爷爷辈,祖宗背继承(正常理解的继承)下来)获得他们的某种(或全部的)性质。
  • 多态:就是说,龙生九子,各个不同嘛。你继承来的东西(性质),可以发生变化的,这种多样性就是多态嘛。

之前我们说过"程序是指令的集合",我们在程序中书写的语句在执行时会变成一条或多条指令然后由CPU去执行。当然为了简化程序的设计,我们引入了函数的概念,把相对独立且经常重复使用的代码放置到函数中,在需要使用这些功能的时候只要调用函数即可;如果一个函数的功能过于复杂和臃肿,我们又可以进一步将函数继续切分为子函数来降低系统的复杂性。但是说了这么多,不知道大家是否发现,所谓编程就是程序员按照计算机的工作方式控制计算机完成各种任务。但是,计算机的工作方式与正常人类的思维模式是不同的,如果编程就必须得抛弃人类正常的思维方式去迎合计算机,编程的乐趣就少了很多,"每个人都应该学习编程"这样的豪言壮语就只能说说而已。当然,这些还不是最重要的,最重要的是当我们需要开发一个复杂的系统时,代码的复杂性会让开发和维护工作都变得举步维艰,所以在上世纪60年代末期,"软件危机"、"软件工程"等一系列的概念开始在行业中出现。

当然,程序员圈子内的人都知道,现实中并没有解决上面所说的这些问题的"银弹",真正让软件开发者看到希望的是上世纪70年代诞生的Smalltalk编程语言中引入的面向对象的编程思想(面向对象编程的雏形可以追溯到更早期的Simula语言)。按照这种编程理念,程序中的数据和操作数据的函数是一个逻辑上的整体,我们称之为“对象”,而我们解决问题的方式就是创建出需要的对象并向对象发出各种各样的消息,多个对象的协同工作最终可以让我们构造出复杂的系统来解决现实中的问题。

说明: 当然面向对象也不是解决软件开发中所有问题的最后的“万能药”,所以今天的高级程序设计语言几乎都提供了对多种编程范式的支持,Python也不例外。


一.类和对象

简单的说,类是对象的蓝图和模板,而对象是类的实例。这个解释虽然有点像用概念在解释概念,但是从这句话我们至少可以看出,类是抽象的概念,而对象是具体的东西。在面向对象编程的世界中,一切皆为对象,对象都有属性和行为,每个对象都是独一无二的,而且对象一定属于某个类(型)。当我们把一大堆拥有共同特征的对象的静态特征(属性)和动态特征(行为)都抽取出来后,就可以定义出一个叫做“类”的东西。

多态性

二.定义类

在Python中可以使用class关键字定义类,然后在类中通过之前学习过的函数来定义方法,这样就可以将对象的动态特征描述出来,代码如下所示。

class Student(object):
    # __init__是一个特殊方法用于在创建对象时进行初始化操作
    # 通过这个方法我们可以为学生对象绑定name和age两个属性
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def study(self, course_name):
        print('%s正在学习%s.' % (self.name, course_name))

    # PEP 8要求标识符的名字用全小写多个单词用下划线连接
    # 但是部分程序员和公司更倾向于使用驼峰命名法(驼峰标识)
    def watch_movie(self):
        if self.age < 18:
            print('%s只能观看《哆啦A梦》.' % self.name)
        else:
            print('%s正在观看玄幻动作大片.' % self.name)

说明: 写在类中的函数,我们通常称之为(对象的)方法,这些方法就是对象可以接收的消息。

三.创建和使用对象

当我们定义好一个类之后,可以通过下面的方式来创建对象并给对象发消息。

def main():
    # 创建学生对象并指定姓名和年龄
    stu1 = Student('晶晶', 16)
    # 给对象发study消息
    stu1.study('Python小白之路')
    # 给对象发watch_av消息
    stu1.watch_movie()
    stu2 = Student('小可爱', 22)
    stu2.study('思想品德')
    stu2.watch_movie()


if __name__ == '__main__':
    main()

# 晶晶正在学习Python小白之路.
# 晶晶只能观看《哆啦A梦》.
# 小可爱正在学习思想品德.
# 小可爱正在观看玄幻动作大片.

四.访问可见性问题

对于上面的代码,有C++、Java、C#等编程经验的程序员可能会问,我们给Student对象绑定的name和age属性到底具有怎样的访问权限(也称为可见性)。因为在很多面向对象编程语言中,我们通常会将对象的属性设置为私有的(private)或受保护的(protected),简单的说就是不允许外界访问,而对象的方法通常都是公开的(public),因为公开的方法就是对象能够接受的消息。在Python中,属性和方法的访问权限只有两种,也就是公开的和私有的,如果希望属性是私有的,在给属性命名时可以用两个下划线作为开头,下面的代码可以验证这一点。

class Test:

    def __init__(self, foo):
        self.__foo = foo

    def __bar(self):
        print(self.__foo)
        print('__bar')


def main():
    test = Test('hello')
    # AttributeError: 'Test' object has no attribute '__bar'
    test.__bar()
    # AttributeError: 'Test' object has no attribute '__foo'
    print(test.__foo)


if __name__ == "__main__":
    main()

但是,Python并没有从语法上严格保证私有属性或方法的私密性,它只是给私有的属性和方法换了一个名字来妨碍对它们的访问,事实上如果你知道更换名字的规则仍然可以访问到它们,下面的代码就可以验证这一点。之所以这样设定,可以用这样一句名言加以解释,就是"We are all consenting adults here"。因为绝大多数程序员都认为开放比封闭要好,而且程序员要自己为自己的行为负责。

class Test:

    def __init__(self, foo):
        self.__foo = foo

    def __bar(self):
        print(self.__foo)
        print('__bar')


def main():
    test = Test('hello')
    test._Test__bar()
    print(test._Test__foo)


if __name__ == "__main__":
    main()

对比两种你会发现,其实就是只是换了一种方法让你访问,而且是一种算是通用的访问私有属性和方法的法子。就像你做了一个防火墙,其实为了出现意外或者不可预知的风险,你会六个后门,就比如说前几年那个有名的勒索病毒嘛,最后传播的范围太大,也就是出现了不可控不可预知的情况,最后用了那个当初留的后门才解决的嘛。不同的是,这种后门只有他一个人知道,而我们现在学的Python这个私有属性的访问方法大多数人都知道。

在实际开发中,并不建议将属性设置为私有的,因为这会导致子类无法访问(后面会讲到)。所以大多数Python程序员会遵循一种命名惯例就是让属性名以单下划线开头来表示属性是受保护的,本类之外的代码在访问这样的属性时应该要保持慎重。这种做法并不是语法上的规则,单下划线开头的属性和方法外界仍然是可以访问的,所以更多的时候它是一种暗示或隐喻,关于这一点可以看看我的《Python - 那些年我们踩过的那些坑》文章中的讲解。

五.面向对象的支柱

面向对象有三大支柱:封装、继承和多态。后面两个概念在下一个章节中进行详细的说明,这里我们先说一下什么是封装。我自己对封装的理解是"隐藏一切可以隐藏的实现细节,只向外界暴露(提供)简单的编程接口"。我们在类中定义的方法其实就是把数据和对数据的操作封装起来了,在我们创建了对象之后,只需要给对象发送一个消息(调用方法)就可以执行方法中的代码,也就是说我们只需要知道方法的名字和传入的参数(方法的外部视图),而不需要知道方法内部的实现细节(方法的内部视图)。

六.练习

练习1:定义一个类描述数字时钟。

from time import sleep


class Clock(object):
    """数字时钟"""

    def __init__(self, hour=0, minute=0, second=0):
        """初始化方法

        :param hour: 时
        :param minute: 分
        :param second: 秒
        """
        self._hour = hour
        self._minute = minute
        self._second = second

    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

    def show(self):
        """显示时间"""
        return '%02d:%02d:%02d' % \
               (self._hour, self._minute, self._second)


def main():
    clock = Clock(23, 59, 58)
    while True:
        print(clock.show())
        sleep(1)
        clock.run()


if __name__ == '__main__':
    main()

# 这里设定的这个时钟的开始时间是根据你使用函数时输入的参数来的。 
# 这里的话就是用的while True 嘛,这样程序就会无限运行,而且每次休息一秒,
# 也就是函数run()运行的频率。run()函数中的三层迭代就是时间的进制嘛。

练习2:定义一个类描述平面上的点并提供移动点到另一个点距离的计算方法。

from math import sqrt


class Point(object):

    def __init__(self, x=0, y=0):
        """初始化方法
        
        :param x: 横坐标
        :param y: 纵坐标
        """
        self.x = x
        self.y = y

    def move_to(self, x, y):
        """移动到指定位置
        
        :param x: 新的横坐标
        "param y: 新的纵坐标
        """
        self.x = x
        self.y = y

    def move_by(self, dx, dy):
        """移动指定的增量
        
        :param dx: 横坐标的增量
        "param dy: 纵坐标的增量
        """
        self.x += dx
        self.y += dy

    def distance_to(self, other):
        """计算与另一个点的距离
        
        :param other: 另一个点
        """
        dx = self.x - other.x
        dy = self.y - other.y
        return sqrt(dx ** 2 + dy ** 2)

    def __str__(self):
        return '(%s, %s)' % (str(self.x), str(self.y))


def main():
    p1 = Point(3, 5)
    p2 = Point()
    print(p1)
    print(p2)
    p2.move_by(-1, 2)
    print(p2)
    print(p1.distance_to(p2))


if __name__ == '__main__':
    main()

# (3, 5)
# (0, 0)
# (-1, 2)
# 5.0

总结

主要是认识了面向对象编程的基本属性以及基本模样。三种面向对象的三大支柱,封装,继承和多态;然后还有类里面关于方法和变量的访问可见性问题;最后就是通过两个练习,再一次重新认识了一下类的相关内容,加强了对相关知识的理解。

溜了遛了,脑壳疼。Loading(08/100)。。。。

国网DLT698.45协议——采集系统、数据交换(一) 对于国网698协议,是一种面向对象的通信协议,用于远程监控和控制电力系统中的设备。面向对象使得对协议的思考更趋向于正常思维,使计算机中描述的抽象世界于现实世界中能够更好的对应起来。协议中就是将各种方法和属性对应描述成类和对象。接下来是我学习该协议的一些总结和认识,欢迎大家随时在评论区或者私信我交流学习。:系统=对象+消息:程序=算法+数据对象和接口类描述:类描述了一组具有相同属性和相同方法的对象。 阅读详情

相关推荐

PCB设计教程【入门篇】——PCB设计基础-PCB构成与组成

本教程基于B站Expert电子实验室的PCB设计教学的整理,为个人学习记录,旨在帮助PCB设计新手入门。所有内容仅作学习交流使用,无任何商业目的。若涉及侵权,请随时联系,将会立即处理。

2501_91732643的博客 7647

面向对象

有一种编程方式叫做面向对象编程,和传统的面向过程式编程方式相对。 那么是面向对象编程? 为什么要面向对象编程,因为面向对象有很多好处。

u012281814的专栏 567

STM32L452与FPGA通信翻车?手把手教你关闭I2C时钟延展避坑(附OVR错误解决方案)

本文深入解析STM32L452与FPGA在I2C通信中因时钟延展功能导致的常见问题,提供关闭I2C时钟延展的详细配置方法(NOSTRETCH模式),并针对可能出现的OVR错误给出Combined模式解决方案。通过实战案例和波形分析,帮助工程师快速排查和解决嵌入式系统中的I2C兼容性问题。

e3f4g5的博客 215

【“笨办法”学Python】43.基本的面向对象分析和设计——自顶向下、自底向上

43.基本的面向对象分析和设计 文章目录前言一、Atom文本编辑器二、运行Python程序总结 前言   程序的注释很重要!有两个重要的作用: (1) 说明某段代码的作用。 (2) 临时禁用这段代码。    # 号,英文为octothorpe或者pound character。 一、Atom文本编辑器   注释的作用。 # A comment, this is so you can read your program later. # Anything after the # is ignore

每天都在学习的小博主 6700

Matlab双目相机标定

1 概述 现在有许多双目相机在出厂时就已经标定好了,用户拿到手后可以直接使用,例如Intel Realsense系列。但是有些相机出厂的时候并没有完成标定工作,因而这个时候就需要我们自己来标定。由于笔者曾改装过一个双目相机,最远可以测至50m,因此有一定的心得体会想给大家分享一下。本文主要介绍双目相机标定的整个过程,以及导出标定数据的方法。 相机标定主要分为手动标定和自动标定,手动标定比较繁琐,这里主要介绍基于matlab工具箱的自动标定方式来对双目相机进行标定。具体的相关标定细节也可以参照这篇博客:m

weixin_46133643的博客 2万+

MT25QL256完整操作指南:从ID读取到4KB扇区擦除(附华大SPI例程)

本文提供了MT25QL256 NOR FLASH在华大MCU上的完整驱动开发指南。内容涵盖从SPI初始化、器件ID读取、状态寄存器查询,到核心的页编程和4KB扇区擦除操作,并分享了构建健壮驱动框架、处理跨页写入及常见调试问题的实战经验。

tt34567的博客 886

Effective Python 读书笔记 - 第27条:多用public属性,少用private属性

与C++和Java不同的是,对Python类来说,其属性的可见度只有两种,也就是public和private。 class MyObject(object): def __init__(self): self.public_field = 5 self.__private_field = 10 def get_private_field(sel...

u012439764的博客 463

Open3D (C++) 泊松重建【2025最新版】

使用C++版本的Open3D实现点云的泊松重建

点云侠的博客 3077

浅谈Python中对象是如何被调用的

本文主要介绍了浅谈Python中对象是如何被调用的,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,PyType_Type内部的tp_call是一个函数指针,这在Python的层面上我们已经验证过了,下面我们再来通过源码看一下。对于内置类型的实例对象而言,这两种方式都是支持的,比如列表,我们即可以通过[]创建,也可以通过list(),前者是Python/C API,后者是调用类型对象。可能有人奇怪了,为什么列表不行呢?

weixin_45841831的博客 1768

Halcon 形态学 开发案例 (开运算opening(先腐蚀再膨胀)、闭运算closing(先膨胀再腐蚀))

算子方法:功能:使用用户自定义的结构元素对区域进行开运算参数: Region(输入参数) :输入区域 StructElement(输入参数) :结构元素(区域) RegionOpening(输出参数) :开运算后的区域功能:使用圆形结构元素对区域进行开运算参数: Region(输入参数) :输入区域 RegionOpening(输出参数) :开运算后的区域 Radius(输入参数) :圆形结构元素的半径功能:使用矩形结构元素对区域进行开运算。

程序员,他们想的是什么?他们想的永远都是技术,他们崇尚的也永远都是技术。 1618

092、Python在芯片验证中的应用:从脚本小子到验证架构师

Python在芯片验证中的高效应用 本文通过实际案例展示了Python在芯片验证中的关键作用。凌晨三点的调试场景揭示了传统方法的局限,Python脚本能在20分钟内分析80GB波形数据定位FIFO指针问题。文章重点介绍了两个核心工具: 智能日志分析系统:通过正则表达式和上下文分析,自动分类百万行验证日志中的错误,生成可视化报告,效率远超传统grep方法。 寄存器模型生成器:将Excel表格自动转换为UVM寄存器模型代码,将原本需要两周的手工工作缩短至两小时,同时保证零错误。 文章还展示了Python与Sys

z534437748的博客 72

python:定义一个类描述平面上的点并提供移动点和计算到另一个点距离的方法。

定义一个类描述平面上的点并提供移动点和计算到另一个点距离的方法。 from math import sqrt class Point(object): def __init__(self, x=0, y=0): &quot;&quot;&quot; 构造器 :param x: 横坐标 :param y: 纵坐标 &quot;&quot;&quot; ..

Darkman_EX的博客 7099

2026年【江苏“信息与未来”编程思维】真题及题解(T6:桌面游戏)

2026年【江苏“信息与未来”编程思维】真题及题解(T6:桌面游戏)

王老师青少年编程 534

Day08 - 面向对象编程基础

Day08 - 面向对象编程基础 活在当下的程序员应该都听过“面向对象编程”一词,也经常有人问能不能用一句话解释下什么是“面向对象编程”,我们先来看看比较正式的说法。 把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的特化(specialization)...

Laic Zhang的博客 1477

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

DAY08-面向对象编程基础

DAY08-面向对象编程基础 本贴主要是讲什么是类,给出了例子来运用于类的继承

sinat_36515789的博客 226

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

python_100天——DAY08_面向对象编程基础

python_100天——DAY08_面向对象编程基础

Xiaowu2048的博客 212

Python学习教程:Day08-面向对象编程基础

面向对象编程基础活在当下的程序员应该都听过“面向对象编程”一词,也经常有人问能不能用一句话解释下什么是“面向对象编程”,我们先来看看比较正式的说法。把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的特化(specialization)和泛化(general...

weixin_34413065的博客 239

Python100天打卡-Day08- 面向对象编程基础

面向对象编程基础 类和对象 简单的说,类是对象的蓝图和模板,而对象是类的实例。 这个解释虽然有点像用概念在解释概念,但是从这句话我们至少可以看出,类是抽象的概念,而对象是具体的东西。 在面向对象编程的世界中,一切皆为对象,对象都有属性和行为,每个对象都是独一无二的,而且对象一定属于某个类(型)。 当我们把一大堆拥有共同特征的对象的**静态特征(属性)和动态特征(行为)**都抽取出来后,就可以定义...

wxl1999的博客 375

Python入门教程100天:Day08-面向对象编程基础

面向对象编程基础活在当下的程序员应该都听过“面向对象编程”一词,也经常有人问能不能用一句话解释下什么是“面向对象编程”,我们先来看看比较正式的说法。把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的特化(specialization)和泛化(general...

weixin_33994444的博客 325

【Python百日基础系列】Day08 - 面向对象编程基础:Class类

文章目录

专注于医院数据分析技术与系统开发的创作与分享。 299

Day08 - 面向对象编程基础(学习笔记)

面向对象编程基础类和对象类的定义对象的定义面向对象的其他概念定义类类的基本结构属性和方法构造器析构器_ _str_ _方法使用对象创建对象--实例化类给对象发消息--调用类属性和方法面向对象的四大支柱抽象封装继承多态基础练习定义学生类定义时钟类定义图形类定义汽车类一.类和对象1.1 类的定义1.2 对象的定义1.3 面向对象中的其他概念二.定义类2.1 基本结构2.2 属性和方法2.3 构造器2.4 析构器2.5 _ _str _ _ 方法 类和对象 类的定义 对象的定义 面向对象的其他概念 定义类 类的基

qq_42999938的博客 209

【搬运自用】Python面向对象编程基础 - 100天从新手到大师Day08(GitHub)

搬运Github热门项目Python从新手到大师Day08内容,仅供自己学习和参考

weixin_57560711的博客 163

Python学习教程(Python学习路线):Day08-面向对象编程基础

Python学习教程(Python学习路线):面向对象编程基础 活在当下的程序员应该都听过“面向对象编程”一词,也经常有人问能不能用一句话解释下什么是“面向对象编程”,我们先来看看比较正式的说法。 把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的...

weixin_30500289的博客 147
上一篇: Day07.字符串和常用数据结构
下一篇: Day10.图形用户界面和游戏开发
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值