快乐学Python,Python基础之组织代码「类与对象」

发布时间:2024年01月08日

在上一篇文章中,我们了解了函数。这一篇文章我们来了解一下Python中另外一个重要的概念:类与对象。

1、类与对象

(1)类与对象有什么关系?

你可能会奇怪,为什么要叫类与对象呢?是两个不同的东西吗?简单来说,类代表一个类别,而对象则代表类的一个实例。比如我们在变量与数据类型中学习的整型变量为例。

a = 3

print(type(a))

输出结果为:

<class 'int'>

我们创建了一个变量 a,并赋值为 3,然后打印了它的类型。可以看到,输出 int,代表整型变量。
细心的你也发现了,输出里面有一个单词 class,它就是类别的意思。难道说?所谓的整型,是一个类?你猜得没错。这里的整型:int,就是一个类。而我们创建的整型变量 a,就是他的一个实例。

我们再举一些生活中的例子:

  • “人”是一个类,小明则是“人”这个类的一个实例,所以小明是一个对象;
  • “打车公司”是一个类,滴滴则是这个类的一个实例对象(也可以隐藏 实例 这个称呼);
  • “酱油”是一个类,海天酱油 则是一个对象;
  • “车”是一个类,奔驰车则是一个对象。

细心的你不难发现,类与对象本质上是抽象与具象的关系,对象在类的基础上进行了适当的具象。所以在某个抽象关系中的对象也可能会成为另一个抽象关系中的类。比如上面奔驰车是车的一个对象,那同样可能存在,奔驰车是一个类,而 S350L 是一个对象。

(2)Python 中的类

理解了类与对象,现在我们来看一下 Python 中的类,我们在开头的例子中提到,类是用来把有联系的数据和函数给组织起来的一种方式。

在类中,数据被称为属性,而函数则被称为方法。每个类都可以有零个或者多个属性,也可以有零个或者多个方法。

类的属性和方法的概念也很适合用来描述现实世界,比如“人”这个类,身高、体重、年龄等就是属性,而走路、吃饭、打球 等动作就是方法。

接下来,我们通过一个例子来演示怎么定义类,怎么使用类。

(3)定义一个“人”的类

现在我们尝试定义一个人的类。需要有年龄、性别、姓名三个属性,并提供两个方法:introduce 方法,打印一句介绍自己的话。get_age 方法,返回当前对象的 age。

# 类的定义环节

class?Person:

????def?__init__(self):

????????self.name?=?""

????????self.age?=?0

????????self.gender?=?""



????def?introduce(self):

????????print("Hello,?我是"?+?self.name)

????????print("我今年?"?+?str(self.age)?+?"?岁")

????????print("另外,?我是"?+?self.gender)



????def?get_age(self):

????????return?self.age

# 使用上面定义的类

xm?=?Person()

xm.name?=?"小明"

xm.age?=?"25"

xm.gender?=?"男生"

print(xm.get_age())

xm.introduce()

简单说一下上面的代码的主要逻辑:

  • 在定义环节:
    • 定义了一个类:Person(类名首字母用大写),并用 init 函数中初始化了三个属性:name,age,gender。(init 函数,前后都有两个下划线,代表初始化函数。简单来说就是,当我们创建这个类的对象的时候,这个函数会被自动执行,不用你再手动执行一下)
    • 定义了 introduce 方法,会把几个属性的值组合成一段自我介绍,这里我们通过方法参数 self.属性名 的形式来拿到类的属性的值。这种形式叫作**点语法。**点语法的本质就是找点前面的对象拿点后面的属性的值。比如 A.B 代表 A对象的B属性的值。
    • 定义了 get_age 方法,把当前对象的 age 对象的值返回。可以看到,无论是 introduce 方法 还是 get_age 方法,都有一个 self 参数。这是 Python 的语法规定,类的方法的第一个参数都必须是 self。这样方法内部就能通过对 self 使用点语法来获取属性的值。
  • 使用环节
    • 注意从我们使用的类的代码开始,我们这里就没有缩进。因为有缩进就会被认为还是在类的内部,但这里的代码是在外部的,所以不用缩进;
    • 我们创建了一个 Person 对象,存在变量 xm 中,之后逐一给它的属性赋值
    • 打印 xm 对象的 get_age 方法返回的值
    • 调用 xm 对象的 introduce

运行后,输出如下所示:


25

Hello, 我是小明

我今年 25 岁

另外, 我是男生

可以看到,通过类的机制,我们成功地把数据和函数绑定在了一起。比如上面例子的数据:name、age、gender 和函数:get_age、introduce。并且类提供了一种机制(self 参数),能够让类的方法可以访问类的属性。

(4)给属性赋值

回看刚刚的例子,我们创建了 Person 类的对象之后,逐一对他的属性赋值,每一次属性赋值都需要针对 xm 对象使用点语法,比较麻烦,有没有更好的方式呢? 答案是肯定的。
我们稍微改造一下刚才的例子,改造后的代码如下所示:

class?Person:

????def?__init__(self,?name,?age,?gender):

????????self.name?=?name

????????self.age?=?age

????????self.gender?=?gender



????def?introduce(self):

????????print("Hello,?我是"?+?self.name)

????????print("我今年?"?+?str(self.age)?+?"?岁")

????????print("另外,?我是"?+?self.gender)



????def?get_age(self):

????????return?self.age

xm?=?Person("小明",?25,?"男生")

print(xm.get_age())

xm.introduce()

执行之后,输出和刚才是一致的:

25

Hello, 我是小明

我今年 25 岁

另外, 我是男生

不同在哪儿呢?是这里。


现在我们不需要进行逐个属性的赋值,而是在构造对象的阶段就完成了几个属性的初始化。

这其中的奥妙就在 init 方法里,我们给 init 函数加了参数,然后用这些参数直接在 __init__的函数体中给我们的属性赋值。这样直接在创建对象的时候,把对应的值依次放在类名后的括号中,用逗号分隔。就能实现一次性地给属性都赋值,精简了代码。

2、常见的系统类

类和函数一样,类同样也有 Python 的开发者们提前写好提供给我们使用的类,一般称为系统类。上面举的例子都是我们自己实现的类,下面来看一下常用的系统类。

(1)列表(list)

列表相信大家都不陌生,在变量与数据类型文章中已经介绍过,它是 Python 非常常用的数据类型。

这里介绍一下列表的基础使用,代码如下:

#?创建列表

a?=?[90,1,23,?15]

#?访问某个元素(下表从?0?开始)

print("Third?number?is?",a[2])

#?使用?append?方法添加元素

a.append(-1)

print("After?append:?",?a)

#?删除某个位置的元素

del?a[1]

print("After?delete?second?number:?",?a)

#?删除具体某个元素

a.remove(15)

print("After?delete?15:",?a)

#?排序,默认从小到大

a.sort()

print("After?sort",?a)

#?逆排序,从大到小

a.sort(reverse?=?True)

print("After?reverse?sort",?a)

#?求长度

print("Length:?",?len(a))

上面主要方法都有注释,这里不再展开,你可以结合以下输出和代码,加深理解。重要的是你要知道,如果之后让你做某个事(删除、排序等),你能直接使用 list 类对应的方法。而不需要自己写循环完成。

Third number is  23

After append:  [90, 1, 23, 15, -1]

After delete second number:  [90, 23, 15, -1]

After delete 15: [90, 23, -1]

After sort [-1, 23, 90]

After reverse sort [90, 23, -1]

Length:  3

(2)字符串(string)

字符串我们用的也是非常多的,在之前也介绍过一些基础用法,比如用 + 号来连接两个字符串,这里我们再介绍额外的一些用法。

a?=?"Hello,this?is?my?home,welcome"

#?添加字符

a?=?a?+?",pp"

print("\nAfter?append?pp:\n",?a)

#?删除前?x?个字符,比如?3

a?=?a[3:]

print("\nAfter?remove?first?3?characters:\n",?a)

#?删除固定内容的字符

a?=?a.replace("my","")

print("\nAfter?remove?'my':\n",?a)

#?替换固定内容成另外一个字符串

a?=?a.replace("home",?"company")

print("\nAfter?replace?'home'?to?'company':\n",a)

#?用某个字符分割字符串,返回一个数组,比如逗号

str_list?=?a.split(",")

print("\nList?split?from?string?by?comma:\n",?str_list)

输出:

After append pp:

 Hello,this is my home,welcome,pp

After remove first 3 characters:

 lo,this is my home,welcome,pp

After remove 'my':

 lo,this is  home,welcome,pp

After replace 'home' to 'company':

 lo,this is  company,welcome,pp

List split from string by comma:

 ['lo', 'this is  company', 'welcome', 'pp']

3、字典(dict)

字典和列表、字符串一样,也是 Python 中相对常用的数据类型,同样也是系统类。因为复杂一些,所以在变量与数据类型文章中没有介绍。

字典和列表类似,也是存储多个变量的容器。但与列表不同的是,字典存储的不仅仅只有变量,还有变量之间的映射关系。

我们举个例子,假设我们要存储班级里三位同学的年龄,可以用列表来完成,比如 a = [17, 18, 15], 但如果我们不仅要存储年龄,还得存储这三位同学的名字。那用列表就无能为力了。

简单来说,我们希望存储一个名字-年龄的映射关系。在这个例子上就是要存储这种形式的数据:小明:17,小红:18,小江:15。在 Python 中,这种有对应关系的两个变量我们称之为键值对。比如小明就是 键(key),而 17 就是值(value),一个键会唯一对应到一个值。

这里我们希望存储的就是三个键值对。而字典,就是专门用来存储键值对的容器。

#?创建一个空字典,用?花括号?{}

d?=?{}

print("Empty?dict:",?d)

#?用键值对创建字典,键和值中间用冒号隔开,不同的键值对用逗号隔开

d?=?{"xiaoming"?:?3.5?,?"xiaohong":?4}

print("Two?key-value?pair?dict:",?d)

#?访问字典的元素,和列表一样用中括号,但传入?key,查询?value。比如查询?xiaoming?的年龄

print("Xiaoming's?company?age:",?d["xiaoming"])

#?添加新的键值对,直接对?key?对应的?value?赋值即可

d["xiaogang"]?=?5.5

print("After?append?xiaogang:",?d)

#?删除键值对,类似列表删除,只是中括号内写?key,而不是序号

del?d["xiaohong"]

print("After?remove?xiaohong:",?d)

#?修改键值对,同添加一样,直接对某个已有的?key?重新赋值即可

d["xiaoming"]?=?9.3

print("After?change?xiaoming's?value:",?d)

输出:

Empty dict: {}

Two key-value pair dict: {'xiaoming': 3.5, 'xiaohong': 4}

Xiaoming's company age: 3.5

After append xiaogang: {'xiaoming': 3.5, 'xiaohong': 4, 'xiaogang': 5.5}

After remove xiaohong: {'xiaoming': 3.5, 'xiaogang': 5.5}

After change xiaoming's value: {'xiaoming': 9.3, 'xiaogang': 5.5}

3、实战

现在有个任务,记录部门信息,每个部门都需要统计部门名称,员工列表,部门主管等信息。另外,还有两个要求:1、部门员工入职和离职都能方便的更新信息;2、可以方便查看某个部门的汇总信息。

问题分析:

  • 目前我们需要记录的信息都是围绕部门这个实体的,所以我们可以用一个部门的类来记录,部门名称、员工列表和部门主管则都是这个类的属性。
  • 另外的要求是有人员变动的时候方便更新信息,那其实就是部门类需要提供增加人员和减少人员的方法。
  • 最后一个要求是方便查看部门汇总,那其实就是需要一个打印方法,来把部门的属性都打印出来。

我们接下来一步步来实现它。

(1)创建部门类

我们首先创建部门类和它的属性,部门名称和主管姓名,是字符串类型的变量,这两个属性我们通过初始化函数的参数来初始化。而员工列表是一个列表类型,我们先把它初始化成一个空列表。

class?Department:

????def?__init__(self, dep_name,?boss_name):

????????self.dep_name?=?dep_name

????????self.boss_name?=?boss_name

????????self.stuff_list?=?[]

(2)实现员工的新增方法

目前员工列表,也就是 stuff_list 属性还是空列表,为了实现往这个列表增加员工的名字,我们需要在部门类增加一个添加员工的方法,我们就命名为 add_stuff。这个方法除了类方法必须带的 self 参数之外,只有一个参数:要添加的员工的姓名。

然后方法里面只需要把这个姓名添加到 stuff_list 即可,添加数据到列表,只需要调用列表对象的 append 方法即可。

class?Department:

????def?__init__(self,dep_name,?boss_name):

????????self.dep_name?=?dep_name

????????self.boss_name?=?boss_name

????????self.stuff_list?=?[]

????#?新增代码

????def?add_stuff(self,?name):

????????self.stuff_list.append(name)

(3)实现删除员工的方法

部门会新增员工,比如员工入职,或者调入。也可能会减少员工,比如员工离职,比如转岗去其他部门,所以我们同样需要一个删除员工的方法。

类似添加员工的设计,删除员工的方法同样需要员工姓名的参数,在方法内部调用 stuff_list 对象的 remove 方法来将员工从列表中移除。

class?Department:

????def?__init__(self,dep_name,?boss_name):

????????self.dep_name?=?dep_name

????????self.boss_name?=?boss_name

????????self.stuff_list?=?[]

????def?add_stuff(self,?name):

????????self.stuff_list.append(name)



????#?新增代码

????def?remove_stuff(self,?name):

????????self.stuff_list.remove(name)

(4)添加打印部门信息的方法

打印部门信息,就是将部门的三个属性直接打印出来,比较简单,这里我们直接实现:

class?Department:

????def?__init__(self,dep_name,?boss_name):

????????self.dep_name?=?dep_name

????????self.boss_name?=?boss_name

????????self.stuff_list?=?[]

????def?add_stuff(self,?name):

????????self.stuff_list.append(name)



????def?remove_stuff(self,?name):

????????self.stuff_list.remove(name)



???? # 打印部门信息
    def print_dep_info(self):
        print("部门名称:",self.dep_name);
        print("主管名称:",self.boss_name);
        #这里使用上一篇文章中说到的len()函数来计算部门人数
        print("员工共个:",len(self.stuff_list));
        print("分别是:",self.stuff_list);

(5)使用部门类

现在,我们的部门类已经开发完毕了,现在让我们来用一用它,看看它是不是好使。

首先是记录部门信息,假设现在先记录2个部门:技术部和财务部。首先要分别创建两个部门的对象:

#创建技术部和财务部
it_dep = Department("技术部","小江");
finance_dep = Department("财务部","小红");

#给技术部添加两个员工
it_dep.add_stuff("小江1");
it_dep.add_stuff("小江2");

#给财务添加两个员工
finance_dep.add_stuff("小红1");
finance_dep.add_stuff("小红2");
#打印技术部和财务部信息
it_dep.print_dep_info();
finance_dep.print_dep_info();

执行后输出:

部门名称: 技术部
主管名称: 小江
员工共个: 2
分别是: ['小江1', '小江2']
部门名称: 财务部
主管名称: 小红
员工共个: 2
分别是: ['小红1', '小红2']

最后,当有人需要离职时,只需要调用 remove_stuff 方法即可,假设 技术部的小江2决定去创业,要离职,我们需要将他从部门列表中移除。

it_dep.remove_stuff("小江2")

it_dep.print_dep_info()

输出

部门: 技术部

主管: 小江

员工共个:1

员工: ['小江1']

可以看到,小江2已经不在员工列表中了。

至此,我们通过类与对象的方法,完成了部门信息统计的任务,并且可以非常方便地处理员工增加和减少的场景。

文章来源:https://blog.csdn.net/u010223407/article/details/135466977
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。