写给Python社群的第6课:终于学习 Python 类和面向对象了,上坡开始
⛳️ 类的简介
Python 中的类本质上也是一种数据类型,对于初学者而言,Python 中【类】这个概念是非常抽象且复杂的,因为其包含很多概念,定义,所以在第一次学习的时候,重点是理解。
在正式学习类之前,需要先了解两种不同的编程思维,第一种是 面向过程 的编程,第二种是 面向对象 的编程,二者的英文单词分别是 OP(Procedure Oriented) 和 OO(Object Oriented),
如何理解 面向过程 和 面向对象 是非常重要的,下面为你带来几种容易理解的解释。
面向过程是一种线性思维,类似做完一件事情,再去完成下一件事情。
面向对象 是将一件事情所涉及的动作打包好,用的时候,拿过来使用。
面向对象 中的局部是 面向过程 的。
⛳️ 面向对象的编程
面向对象是对现实世界的抽象,它会把现实世界中的所有事务都当成 对象 进行处理,这个抽象过程就是面向对象,也是学习阶段最难的点。
将现实事务抽象成对象之后,就会碰到该知识点中最核心的一个概念【类】。
看一下类的定义:
把具有相同特性(属性)和行为(函数)的对象抽象为类。
这样阅读理解起来还是有难度的,那看一下实例。
最常见的类就是人类,先对人这个群体进行抽象,可以得到以下信息。
人有名字
人有年纪
人有身高
人有体重
人有父母
人有血型
……
人会说话
人会走路
人会爬
人会打架
人会睡觉
……
名字、年纪、体重是人的特性,属性,也可以叫做数据,说话、走路、打架是人的行为。
到这里你应该对人类有了一个基本的共识和抽象,我们再总结一下抽象成类的过程。
- 罗列,归纳,把形形色色的人都归为一类,命名为 Person;
- 提取特性,就是人的属性,例如名字,年纪,体重这些数据信息;
- 提取行为,例如说话,走路,爬,打架。
然后就是把人类定义出来,换成代码就是一个类的定义。
🔥 定义类
下面就展示人类 Person 的定义。
class Person():
# 构造函数
# name,age 是属性
def __init__(self,name,age):
# 属性的定义
self.name = name
self.age = age
# 定义方法
def sleep(self):
print("睡觉")
# 定义方法
def run(self):
print("跑步")
# 实例化对象,也叫类的实例化
p = Person('橡皮擦',18)
# 调用对象方法
p.sleep()
上述类的定义并未罗列全部属性和方法,仅作示例展示,其中涉及了类的基本知识如下。
class 关键字
所有类定义必须以 class
关键字开始,与上篇博客使用 def
定义函数一致。
类名 Person
类名格式遵循命名规则,一般大家遵守首字母大写的约定。类名后面是英文小括号(()
)加英文冒号(:
)。
类中第一行一般是文档说明
一个完善的类,默认会添加文档说明,语法格式为三引号包裹字符串,上述代码并未添加,我们对其进行一下补充。
class Person():
"""这是一个人类---文档字符串"""
# 构造函数
# name,age 是属性
def __init__(self,name,age):
# 属性的定义
self.name = name
self.age = age
# 实例化对象,也叫类的实例化
p = Person('橡皮擦',18)
类函数
类函数在类和实例中也叫做方法,在上述代码中出现了一个构造函数/方法,以及 sleep()
和 run()
函数。
类保留函数 __init__
和 self
关键字
保留函数就是我们编写代码时必须使用的函数,无法用其它函数代替,其包含固定函数名,例如前文的 __init__
。
__init__()
被称作构造函数,其功能是在实例化类时进行调用,最精简的格式如下:
def __init__(self):
其参数表中仅包含一个固定参数 self
,该关键字的作用是在实例使用的时候,用于传递实例对象地址,而且需要注意 self
参数是隐性传递的,也就是在实例化对象的时候,并没有给 self
进行赋值。
class Person():
"""这是一个人类---文档字符串"""
# 构造函数
# name,age 是属性
def __init__(self,name,age):
# 属性的定义
self.name = name
self.age = age
# 实例化对象,也叫类的实例化,这里只传递了 name 和 age 两个参数
p = Person('橡皮擦',18)
🔥 类的实例
实例化是一个命令,可以把类通过等号赋值给一个变量的过程,该过程就是实例化过程。示例代码已经在前文出现过:
p = Person('橡皮擦',18)
你可以由一个类实例化多个对象,并且每个对象之间互不影响。
p1 = Person('橡皮擦',18)
p2 = Person('擦哥',19)
类的实例对象可以调用其属性和方法,互相也没有影响。
class Person():
"""这是一个人类---文档字符串"""
# 构造函数
# name,age 是属性
def __init__(self,name,age):
# 属性的定义
self.name = name
self.age = age
def run(self):
print(self.name,'正在跑步')
# 实例化对象,也叫类的实例化,这里只传递了 name 和 age 两个参数
p1 = Person('橡皮擦',18)
p2 = Person('擦哥',20)
p1.run()
p2.run()
上述代码的输出可以看出 Person 实例化出的 p1
和 p2
在调用 run()
方法时,都输出了自己的姓名属性,即不同的 name
值。
同时类的实例在调用属性或者方法的时候,通过点号(.
)实现,示例代码如下:
# 实例化对象,也叫类的实例化,这里只传递了 name 和 age 两个参数
p1 = Person('橡皮擦',18)
p2 = Person('擦哥',20)
print(p1.name) # 通过点号调用属性
p1.run() # 通过点号调用方法
p2.run()
🔥 属性
属性是通过 _init__()
函数进行定义的,实例化的时候需要通过 self
参数传递值,初始化属性有两种方法,具体如下所示。
在 __init__()
中直接初始化值,例如下述代码将 name
,age
直接赋值。
class Person():
"""这是一个人类---文档字符串"""
# 构造函数
# name,age 是属性
def __init__(self):
# 属性的定义
self.name = '橡皮擦'
self.age = 18
也可以实例化的时候,进行初始化操作。
class Person():
"""这是一个人类---文档字符串"""
# 构造函数
# name,age 是属性
def __init__(self,name,age):
# 属性的定义
self.name = name
self.age = age
p1 = Person('橡皮擦',18)
还可以在实例化对象之后,直接设置属性值,请查看下述代码中 p.name
部分。
class Person():
"""这是一个人类---文档字符串"""
# 构造函数
# name,age 是属性
def __init__(self):
pass
def run(self):
print(self.name,'正在跑步')
# 实例化对象
p = Person()
p.name = '橡皮擦'
p.run()
如果希望修改属性值,可以直接对属性值进行操作,例如下述代码,直接操作属性 name
,对其进行重新赋值。
class Person():
"""这是一个人类---文档字符串"""
# 构造函数
def __init__(self):
self.name = '直接赋值'
def run(self):
print(self.name,'正在跑步')
# 实例化对象
p = Person()
p.name = '橡皮擦'
p.run()
实战中,还可以通过对象方法进行重新赋值。
class Person():
"""这是一个人类---文档字符串"""
# 构造函数
# name,age 是属性
def __init__(self):
self.name = '直接赋值'
# 修改 name
def change_name(self,new_name):
self.name = new_name
def run(self):
print(self.name,'正在跑步')
# 实例化对象
p = Person()
p.change_name('新橡皮擦') # 通过对象方法修改属性值
p.run()
🔥 类的继承和方法重写
在实战中有时候需要扩展一个类,或者重新类中的某些函数,例如之前声明了一个人类,在此基础上可以扩展一个孩子类,代码如下。
class Person():
"""这是一个人类---文档字符串"""
# 构造函数
def __init__(self,name,age):
self.name = name
# 修改 name
def change_name(self,new_name):
self.name = new_name
def run(self):
print(self.name,'正在跑步')
class Children(Person):
def __init__(self,name):
super().__init__(name,0)
def say(self):
print("哇哇哇~")
c = Children('新娃娃')
c.say()
继承就是在原有类的功能上新增功能(属性或方法),形成新的子类,被集成的类叫做父类或者基类,子类也叫做派生类,都是概念,对比牢记。还有一个知识点需要记忆,一个类可以继承多个父类。
再次对比代码学习一下继承的使用流程。
- 在子类声明的时候,需要引入父类名称,例如
Children(Person)
; - 需要重新给子类定义
__init__()
函数,如果父类__init__()
函数有参数,二者尽量保持一致; - 如果需要同步参数,需要用到
super()
函数; - 可以为子类增加新属性或者新方法。
继承父类之后,除了新增方法以外,还可以重写父类的方法,也就是在子类中定义一个与父类同名的函数。
class Person():
"""这是一个人类---文档字符串"""
# 构造函数
def __init__(self,name,age):
self.name = name
# 修改 name
def change_name(self,new_name):
self.name = new_name
def run(self):
print(self.name,'正在跑步')
class Children(Person):
def __init__(self,name):
super().__init__(name,0)
def say(self):
print("哇哇哇~")
def run(self):
print("小孩子,不会跑,只会爬~")
c = Children('新娃娃')
c.run()
🔥 类的私有属性和方法
在实战编码的时候经常会碰到定义一些私有属性或方法的场景,也就是类的部分成员只允许在类内部使用,此时就会用到私有概念,编写规则非常简单,在普通属性或方法前增加两个下划线(__
),示例代码如下。
class Person():
"""这是一个人类---文档字符串"""
# 构造函数
def __init__(self,name,age):
self.__name = name
# 修改 name
def change_name(self,new_name):
self.name = new_name
def run(self):
print(self.name,'正在跑步')
p = Person('新娃娃',18)
p.name
此时在调用 p.name
会出现如下错误,提示信息为 ‘Person’ 类不包含属性 name
。
AttributeError Traceback (most recent call last)
<ipython-input-16-39fea822b3f1> in <module>
15
16 p = Person('新娃娃',18)
---> 17 p.name
18
AttributeError: 'Person' object has no attribute 'name'
🔥 静态类
常见可实例化的类都是动态类,Python 中存在一种不可实例的类,其叫做静态类,静态类和动态类的区别如下。
- 静态类没有关键字
self
,所以其不能被实例化; - 静态类不能通过类名传递参数;
- 静态类虽然不能被实例化,但也具备属性和方法。
静态类的声明。
class StaticPersoon():
name = 'CA'
age = 18
def run():
print("跑步")
由于静态类不能被实例化,所以其使用的时候需要直接用类型调用,如下所示。
class StaticPersoon():
name = 'CA'
age = 18
def run():
print("跑步")
print(StaticPersoon.name)
🔥 类的其它知识
掌握类之后,就掌握类面向对象的编程方法,该方法有三大核心方法,分别是 【封装】、【继承】、【多态】,这些概念在本篇博客不做过多展开,等我们掌握模块并对模块熟悉之后,我们会继续对其复盘说明。
📢📢📢📢📢📢
💗 你正在阅读 【梦想橡皮擦】 的博客
👍 阅读完毕,可以点点小手赞一下
🌻 发现错误,直接评论区中指正吧
📆 橡皮擦的第 744 篇原创博客
- 点赞
- 收藏
- 关注作者
评论(0)