Python面向对象总结一

news2024/11/23 19:39:48

还记得第一次接触Python是在刚刚进入大学的第一个学期,之后就没有再使用过python。虽然基本语法,内置函数等没有忘记,但最近的学习中,一直在用python、matlab混合编程,零零散散的知识点、模模糊糊的记忆,有时候令我眼花缭乱。现在趁着闲暇,系统的温习一下python的基础知识。


目录

一、初识对象

二、self参数详解

三、变量的划分(类变量、实例变量、局部变量)

四、实例方法、静态方法、类方法


一、初识对象

我依稀记得,大一上python的某堂课,任课老师让我们用一段python程序描述班级中学生的信息。

A同学回答:我的程序是这样的

student_1={
"姓名":sun,
"性别":男,
"籍贯":河南,
年龄:18
}

A同学选择使用字典来描述信息。

B同学回答:我的程序是这样的

student_2=["王五","南京","男",19]

他使用列表描述学生信息。

C同学回答道:我选择使用字符串描述信息

student_3="张柳来自福建省,他是男生,今年19岁"

 不难看出,由于不同的同学采用不同数据类型的变量来描述学生信息,使得数据很乱。我们有没有什么其他办法来统一数据格式,使得学生信息看起来整齐有序呢?

我们发现要描述一个学生的信息,形式是多样的(比如使用列表,字典等),但是无论是什么形式都需要包含姓名,年龄,性别,籍贯几个要素。不同的学生的姓名、年龄等个不相同,但是要描述清楚这个学生的信息,总得有这几个要素。如果我们使用一个“模板”,这个“模板”中包含姓名、性别、年龄、籍贯这几个要素,那么这个“模板”肯定能描述清楚任何一个特定学生的信息。因为任何一个特定的学生信息都是从这个“模板”中得来的,数据格式就变得整齐有序了。

上面这个过程其实就是使用对象来组织数据,其形式如下:

class Student:
    name:None
    age:None
    sex:None
    birthPalce:None

 那么A、B、C三位同学的程序就可以统一为:

stu_1=Student()
stu_1.name="sun"
stu_1.age=18
stu_1.sex="男"
stu_1.birthPalce="河南"

stu_2=Student();
stu_2.name="王五"
stu_2.age=19
stu_2.sex="男"
stu_2.birthPalce="南京"

stu_3=Student();
stu_3.name="张柳"
stu_3.age=19
stu_3.sex="男"
stu_3.birthPalce="福建"

 在上面的几段程序中

class Student:
    name:None
    age:None
    sex:None
    birthPalce:None 

称为设计类。其中name,age,sex等称为类的属性,它是用来描述类的特征。比如,一个学生年龄19岁,籍贯河南,姓名李华,这里的年龄、籍贯、姓名就是这个学生的特征(或者称为属性),而19岁、河南,李华就是对应属性的值。又比如,丽丽长的很漂亮,这里丽丽的属性就是“外貌’,而对应的属性值是“漂亮”。其实,要全面描述清楚一个学生,单凭使用“年龄”“姓名”“外貌”等属性是描述不清的,一个学生还可以学习、社交、考试等等,我们无法使用属性来解释学生的这些行为。这时候就要使用“方法”来描述了,现在我们来拓展一下上面的学生类,在类中添加学生的“行为”:

class Student:
    name:None
    age:None
    sex:None
    birthPalce:None 

    def study(self):

            print(f"大家好,我是{self.name},我非常擅长数学,如果有数学难题,欢迎一起探讨") 

 我们在类中定义了一个函数"study"来描述学生的学习行为,这里在类中定义的函数就称为类的成员方法,它是用来描述类的功能。在方法定义的参数列表中,有一个self关键字,它是用来表示类对象自身的意思当我们使用类对象调用方法的是,self会自动被python传入。关于self参数,在本篇文章的下一个章节会详细介绍。

在上面的程序段中:

stu_1=Student()

stu_2=Student();

stu_3=Student();

称为创建对象。为什么非要创建对象才能使用呢?类是程序中的“设计图纸”,而对象是基于图纸生产的具体实体,只要创建出对象,才能用实体去实现类的功能。

类只是一种程序内的“设计图纸”,需要基于图纸生产实体(对象),才能正常工作这种套路,称之为:面向对象编程。面向对象编程就是根据实体抽象出共性,设计出类,基于类创建对象,由对象做具体的工作。

我们继续看上面的程序段:

stu_1.name="sun"

stu_1.age=18

stu_1.sex="男"

stu_1.birthPalce="河南"

stu_2.name="王五"

stu_2.age=19

stu_2.sex="男"

stu_2.birthPalce="南京"

stu_3.name="张柳"

stu_3.age=19

stu_3.sex="男"

stu_3.birthPalce="福建"

 称为对象属性赋值。但是在这段对象属性赋值代码中,为对象的属性赋值需要依次进行,略显繁琐。有没有更加高效的方式就完成呢?

答案是肯定的,我们完全可以使用构造方法对成员变量进行赋值。

class Student:
    def __init__(self,name,age,sex,birthPlace):
        self.name=name
        self.age=age
        self.sex=sex
        self.birthPlace=birthPlace

Python类可以使用:__init__()方法,称之为构造方法。
它可以实现:
在创建类对象(构造类)的时候,会自动执行。
在创建类对象(构造类)的时候,将传入参数自动传递给__init__方法使用。借此特性可以给成员变量赋值
值得注意的是:构造方法名称:__init__ 千万不要忘记init前后都有2个下划线,构造方法也是成员方法,不要忘记在参数列表中提供:self

二、self参数详解

self 参数的具体作用是什么呢?举一个例子,如果把类比作造房子的图纸,那么类实例化后的对象是真正可以住的房子。根据一张图纸(类),我们可以设计出成千上万的房子(类对象),每个房子长相都是类似的(都有相同的类变量和类方法),但它们都有各自的主人,那么如何对它们进行区分呢?当然是通过 self 参数,它就相当于每个房子的门钥匙,可以保证每个房子的主人仅能进入自己的房子(每个类对象只能调用自己的类变量和类方法)。也就是说,同一个类可以产生多个对象,当某个对象调用类方法时,该对象会把自身的引用作为第一个参数自动传给该方法。

在上面这段代码中,我们使用Person类创建了两个不同的对象,打印构造方法中的self发现也不同,这一点也恰好印证了:无论是类中的构造函数还是普通的类方法,实际调用它们的谁,则第一个参数 self 就代表谁。

在上面的章节中我们通过生活中的例子,初步认识了对象,学到了如何定义一个类,知道了类中可以包含属性(变量)与方法(函数)。下面我们继续学习在类中定义的变量与函数,加深对python类的认识。

三、变量的划分(类变量、实例变量、局部变量)

类变量是定义在类内,但在函数外部的变量。

实例变量是定义在类的函数体内,并且是以“self.变量名”定义的变量。

局部变量是定义在类的函数体内,但不是以“self.变量名”定义的变量。

3.1类变量


class Person:
    name = "sun"  # 这是一个类变量

    def __init__(self, age):
        self.age = age  # 这是一个实例变量

    def talk(word):
        words = "Hi"+word  # 这是一个局部变量
        print(words)

p1 = Person(12)
p2=Person(18)

#类变量的调用方式
print(Person.name)#调用类变量的第一种方式:类名.变量名
print(p1.name)#调用类变量的第二种方式:对象名.变量名

#类变量为所有实例共享
print(p1.name)
print(p2.name)

#类变量的修改方式
Person.name="张三"#通过类名.变量名的方式对类变量重新赋值
print(Person.name)#类变量的值变为"张三"
print(p1.name)#用对象p1调用类变量发现值变为"张三"
print(p2.name)#用对象p2调用类变量发现值也变为“张三”

在上面的这段代码中name为类变量。并且类变量具有两种调用方式:(1)类名.变量名(2)对象名.变量名。我们还可以通过类名.变量名的方式对类变量的属性值进行重新赋值修改。但是由于类变量为所有实例对象共享,修改类变量后,通过两个不同的实例对象重新调用name类变量,发现变量值也发生改变。

还有一点需要注意的是,通过类对象是无法修改类变量的。通过类对象对类变量赋值,其本质将不再是修改类变量的值,而是在给该对象定义新的实例变量。看如下代码:

class Student:
    name="王同学"
    def __init__(self,age):
        self.age=age
s1=Student(16)
s1.name="王五"
print(s1.name)
print(Student.name)

王五
王同学

不仅可以通过类名.变量名的方式修改类中已有的类变量,还可以动态添加没有的类变量。

在上段代码中添加以下代码:

class Person:
    name = "sun" 
    def __init__(self, age):
        self.age = age  
p1 = Person(12)
p2=Person(18)
Person.sex="男"
print(Person.sex)
print(p1.sex)
print(p2.sex)

 运行结果



3.2 实例变量 

下面的代码中age,name为实例变量,其中,由于 __init__() 函数在创建类对象时会自动调用,而 learn() 方法需要类对象手动调用。因此,Person类的类对象都会包含 age实例变量,而只有调用了 learn() 方法的类对象,才包含 name实例变量。它们都可以通过对象名.变量名的方式调用

class Person:
    def __init__(self, age):
        self.age = age  # 这是一个实例变量
    def learn(self):
        self.name="sun"#这也是一个实例变量
#实例变量调用方式:对象名.变量名
p1=Person(18)
p2=Person(19)
print(p1.age)
print(p2.age)
#p2对象调用learn方法后再调用name属性
p2.learn()
print(p2.name)
#p1对象在没有调用learn方法时直接调用name
print(p1.name)#直接报错

18
19
sun
Traceback (most recent call last):
  File "e:\VsCodeWorkSpace\PythonProjects\PythonDemo\vari.py", line 76, in <module>
    print(p1.name)#直接报错
AttributeError: 'Person' object has no attribute 'name' 

值得注意的是,如果类变量与实例变量同名,它会首选实例变量。看下面的例子

class Student:
    name="王同学"
    def __init__(self,name):
        self.name=name
s1=Student("王五")
print(s1.name)
print(Student.name)

王五
王同学

另外,和类变量不同,通过某个对象修改实例变量的值,不会影响类的其它实例化对象,更不会影响同名的类变量。例如:

class Person:
    def __init__(self, age):
        self.age = age  # 这是一个实例变量
p1=Person(18)
p2=Person(19)
print(p1.age)#18
print(p2.age)#19
#修改p1的age值
p1.age=20
print(p1.age)#20
print(p2.age)#19

 可以看出,对p1对象的age修改值,并不会影响到p2的age

3.3 局部变量

下面的代码段中c就是一个定义在函数内部的局部变量

class add:
    def sum(self,a,b):
        c=a+b
        print(c)
s=add()
s.sum(1,2)

需要注意的一点是,局部变量只能用于所在函数中,函数执行完成后,局部变量也会被销毁。

在这一章节,我们对python类中的属性(变量)进行了比较深入的分析,和类属性一样,类方法也可以进行更细致的划分,下面我们按照这个思路继续分析类中的方法(函数)

四、实例方法、静态方法、类方法

 采用 @classmethod 修饰的方法为类方法;采用 @staticmethod 修饰的方法为静态方法;不用任何修改的方法为实例方法

4.1 实例方法

class math:
    def sum(self,var1,var2):
        return var1+var2

上面这段代码中的sum方法就是一个实例方法,实例方法最大的特点就是,它最少也要包含一个 self 参数,用于绑定调用此方法的实例对象。实例方法通常可以用对象直接调用,也可以使用类名调用(但此方式需要手动给 self 参数传值)

class Math:
    def sum(self,var1,var2):
        return var1+var2
m=Math()
print(m.sum(2,3))#使用对象调用实例方法
print(Math.sum(m,2,6))#使用类名调用实例方法,但是必须传入对象本身

值得注意的是,类的构造方法也是一种实例方法。

4.2 类方法
与实例方法相似,类方法最少也要包含一个参数,只不过类方法中通常将其命名为 cls,Python 会自动将类本身绑定给 cls 参数(注意,绑定的不是类对象)。也就是说,我们在调用类方法时,无需显式为 cls 参数传参。

调用类方法的方式也有两种:(1)使用类名.方法名(2)使用对象名.方法名

class Math:
    @classmethod
    def sum(cls,var1,var2):
        return var1+var2

print(Math.sum(2,6))#使用类名调用类方法,但是不必显式传入类本身

#也可以使用对象调用类方法
m = Math()
print(m.sum(2,3))

值得注意的是,类方法需要使用@classmethod修饰符进行修饰,上面的sum方法如果不加@classmethod,python会将该方法认定为实例方法

4.3 静态方法

静态方法需要使用@staticmethod修饰,它没有类似 self、cls 这样的特殊参数,因此 Python 解释器不会对它包含的参数做任何类或对象的绑定。也正因为如此,类的静态方法中无法调用任何类属性和类方法。

class Math:
    @staticmethod
    def sum(var1,var2):
        return var1+var2

print(Math.sum(2,6))#使用类名调用静态方法

#也可以使用对象调用静态方法
m = Math()
print(m.sum(2,3))

 到此,通过以上所有的章节我们系统地认识了python对象、类、类的属性、类的方法,有了这些基础,接下来我们继续探讨python封装继承与多态,由于篇幅有限,后续章节会在下一篇博客中介绍。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/20965.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5G无线技术基础自学系列 | 传统无线网络架构

素材来源&#xff1a;《5G无线网络规划与优化》 一边学习一边整理内容&#xff0c;并与大家分享&#xff0c;侵权即删&#xff0c;谢谢支持&#xff01; 附上汇总贴&#xff1a;5G无线技术基础自学系列 | 汇总_COCOgsta的博客-CSDN博客 在4G网络中&#xff0c; 无线侧基本完成…

Anaconda配置镜像源

目录 一、首先生成 Anaconda的 .condarc配置文件&#xff1a; 二、命令行方式配置镜像源 三、可视化界面的方式配置镜像源 一、首先生成 Anaconda的 .condarc配置文件&#xff1a; 打开 Anaconda prompt&#xff0c;敲命令&#xff1a; conda config 查看 .condarc 中的源…

MySQL 增删改查进阶 — 数据库约束

文章目录数据库约束1.约束类型1.1 not null1.2 unique 唯一约束1.3 主键约束 primary key1.4 default 默认值1.5 外键约束 foreign key数据库约束 约束就是让数据库帮助程序猿更好的检查数据是否正确。 1.约束类型 not null - 提示某列不能存储 NULL 值。 允许为空&#xff…

wav to image concat 版

🍿*★,*:.☆欢迎您/$:*.★* 🍿 目录 背景 正文 总结 背景描述

STM32矩阵按键

矩阵按键原理 本实验使用STM32F103单片机&#xff0c;主题代码通用的。 如果每个按键占用一个GPIO引脚&#xff0c;对于使用多个按键来说就是一种资源的浪费&#xff0c;因此当我们在设计时&#xff0c;可以考虑矩阵这种方式。本实验使用4*4也就是16个按键。 矩阵按键相对于独立…

Go 语言搭建个人博客(qiucode.cn 重构篇 三)

1、读取配置文件 项目中如数据库连接、邮箱配置等这些信息一般会被写入一个文件,而通过编码在程序中读取想要的配置信息。 本项目使用yaml文件作为配置文件,配合第三方库viper来读取yaml配置文件。 go get -u github.com/spf13/viper在项目根目录新建一个yaml文件,内容如…

数学杂谈:限制条件下的均匀分布考察

数学杂谈&#xff1a;限制条件下的均匀分布考察 1. 问题描述2. 问题解答 1. 答案2. 解析3. 蒙特卡洛模拟 3. 离散情况延拓 1. 正整数的情况2. 整数的情况3. N→∞N \to \inftyN→∞的情况 4. 误区分析 1. 问题描述 假设x1,...,xnx_1, ..., x_nx1​,...,xn​均为0∼10 \sim 10…

思科防火墙解析(ASA)

♥️作者&#xff1a;小刘在C站 ♥️每天分享云计算网络运维课堂笔记&#xff0c;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的&#xff0c;绽放。 目录 一. 防火墙的分类&#xff0c; 二. 发展史&#xff0c; 三. 思科防火墙技术应用的…

[附源码]java毕业设计铁东社区新冠病毒疫苗接种管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

山东大学线性代数-4-线性方程组

目录 4.1 齐次线性方程组 4.1.1 齐次线性方程组的定义 4.1.2 方程组的三种形式 4.1.3 齐次线性方程组解的性质 4.1.4 行最简形矩阵 4.1.5 两个例题 4.2 基础解系的求法 4.2.1 求解步骤 4.2.2 例题 4.3 非齐次线性方程组 4.3.1 相关概念 4.3.2 非齐次线性方程组的有…

编译安装php扩展

1. 切换到要安装的扩展的目录下 2. 执行phpize(在扩展目录里 可以写自己电脑里的绝对路径) ../../bin/phpize 3. 然后执行 ./configure ./configure 4. 没问题的话 make 然后 make install make 运行之后出现下图就说明可以下一步了 运行 make install make install 出现…

GitHub使用教程

目录概要一. 下载git二. 初始化本地仓库设置签名查看状态&#xff0c;三大分区&#xff0c;添加&#xff0c;提交操作查看状态&#xff0c;三大分区添加查看提交历史查看提交历史的其他指令如何进行版本切换基于索引值基于^符号进行版本切换基于~符号进行版本切换reset指令的参…

【OS】新国立nus操作系统知识点(中文版)

文章目录1. Introduction to OS本章涉及1.1 什么是操作系统&#xff1f;1.2 为什么我们需要操作系统&#xff1f;抽象 Abstraction控制程序Summary1.3 现代操作系统分类1.4 操作系统结构OS结构OS是一个程序OS的实现单片OS Monolithic OS微核OS Microkernel虚拟机 Virtual Machi…

22071.11.20作业

在串口工具进行输入&#xff1a; echo 1 > /dev/myled0 ---->led1灯点亮 echo 0 > /dev/myled0 ---->led1灯熄灭 echo 1 > /dev/myled1 ---->led2灯点亮 echo 0 > /dev/myled1 ---->led2灯熄灭 echo 1 > /dev/myled2 ----&g…

项目实战——创建个人中心页面(上)

ps&#xff1a;本篇文章不涉及复杂代码编写&#xff0c;放心食用~~ 目录 一、整体框架 二、创建新表 bot 三、实现后端API 1、连接数据库和后端 2、实现 增删改查 API 1、增加一个 Bot 2、删除一个 Bot 3、修改一个 Bot 4、查询 Bot 列表 一、整体框架 二、创建新表 bo…

攻防世界nice_bgm

nice_bgm 题目描述&#xff1a;我拿出自己的私密音乐来和你分享&#xff0c;一起享受快乐吧 题目环境&#xff1a;https://download.csdn.net/download/m0_59188912/87097729 private bit隐写&#xff0c;直接用python脚本跑。 脚本源码&#xff1a; import re import binascii…

光线追踪与全域光渲染keyshot中文

keyshot可以快速、轻松地创神奇的渲染和动画效果&#xff0c;支持Mac和PC上的多种3D文件格式。它可以实时查看效果&#xff0c;使用方便&#xff0c;可以更快地创造视觉效果&#xff1b;材料超越了材料的外观&#xff0c;为高质量的视觉效果提供了科学准确的性能&#xff0c;使…

babel:无法将“babel“项目识别问题

全局安装babel命令 npm install --global babel-cli 局部安装babel命令 npm install --save-dev babel-cli 你安装后可能会出现的问题&#xff1a; 可能存在原因&#xff1a; ① 权限不够。 ②前面需改了node的global配置 --------------------------------------------…

i.MX 6ULL 驱动开发 二十三:UART

一、UART 协议 UART详解_sternlycore的博客-CSDN博客 二、UART 和 TTY 关系 基于Linux的tty架构及UART驱动详解 - 一口Linux - 博客园 (cnblogs.com) 三、Linux UART 驱动框架中重要对象 1、UART 驱动 struct uart_driver {struct module *owner;const char *driver_na…

python自动化之——获取钉钉群所有人的昵称

python自动化之——获取钉钉群所有人的昵称 楔子 精神小伙沙大柱入职了一家新公司&#xff0c;该公司所有成员都在钉钉群。 一天&#xff0c;沙大柱的上级沙小牛布置了任务&#xff1a;大柱&#xff0c;你把群里所有人的名称导出来吧&#xff0c;我不会操作。 大柱表示&…