12 KiB
Python 中的类和对象
Python 类和 Python 对象是该语言的重要组成部分。不了解 Python 类和对象,就无法正确学习 Python。在本章中,您将学习:
- 在 Python 中一切都是对象
- 定义自己的 Python 类
- 基于类创建对象
- 什么是继承
当您只是创建小脚本时,您可能不需要创建自己的 Python 类。但是一旦你开始创建更大的应用程序,对象和类允许你自然地组织你的代码。对对象和类的良好理解会帮助你更好地理解语言本身。
目录
- Python 对象:引擎盖下的一瞥
- 什么是 Python 对象?
- 什么是 Python 类?
- 创建一个 Python 类
- 创建一个 Python 对象
- Python 中的 self 是什么?
- 创建多个 Python 对象
- 继续学习
Python 对象:引擎盖下的一瞥
在我们深入了解所有细节之前,让我们先来看看引擎盖下的情况。我这样做是因为我相信这会让你更好地理解这些概念。不要因为这一页的长度而气馁。通读一遍并亲自尝试示例后,您应该对 Python 中的类和对象有了很好的理解。
OK;让我们开始吧!你大概知道内置的len()函数。它只是返回你给它的物体的长度。但是,比如说,数字 5 的长度是多少呢?我们来问问 Python:
>>> len(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()
我喜欢错误,因为它们说明了 Python 内部是如何工作的。在这种情况下,Python 是在告诉我们 5 是一个对象,它没有len()。在 Python 中,一切都是对象。字符串、布尔值、数字,甚至 Python 函数都是对象。我们可以使用内置函数dir()检查 REPL 中的对象。当我们在数字 5 上尝试dir时,它显示了一个函数的大列表,这些函数是任何数字类型对象的一部分:
>>> dir(5)
['__abs__', '__add__',
'__and__', '__bool__',
'__ceil__', '__class__',
...
'__str__', '__sub__',
'__subclasshook__', '__truediv__',
'__trunc__', '__xor__',
'bit_length', 'conjugate',
'denominator', 'from_bytes',
'imag', 'numerator',
'real', 'to_bytes']
为了清楚起见,我把列表缩短了一点。
列表以这些名字古怪的包含下划线的函数开始,比如__add__。这些被称为魔术方法,或 dunder(双下划线的缩写)方法。如果你仔细观察,你会发现对于类型为int的对象没有__len__ dunder 方法。Python 的len()函数就是这样知道一个数没有长度的。所有的len()所做的,就是在你提供给它的对象上调用__len__()方法。这也是 Python 抱怨“‘int’类型的对象没有 len()”的原因
什么是 Python 方法?
我在这里随便介绍了一下方法这个词。让我更正式地定义它:
Method
When a function is part of an object or Python class, we call it a method.
字符串是有长度的,所以一个字符串必须有一个 len 的方法,对吗?让我们来了解一下!
>>> dir("test")
['__add__', '__class__',
'__contains__', '__delattr__',
'__dir__', '__doc__',
'__eq__', '__format__',
'__ge__', '__getattribute__',
'__getitem__', '__getnewargs__',
'__gt__', '__hash__', '__init__',
'__init_subclass__', '__iter__',
'__le__', '__len__', '__lt__',
'__mod__', '__mul__', '__ne__',
'__new__', '__reduce__',
'__reduce_ex__', '__repr__',
'__rmod__', '__rmul__',
'__setattr__', '__sizeof__',
'__str__', '__subclasshook__',
'capitalize', 'casefold', 'center',
'count', 'encode', 'endswith',
'expandtabs', 'find', 'format',
'format_map', 'index', 'isalnum',
'isalpha', 'isascii', 'isdecimal',
'isdigit', 'isidentifier', 'islower',
'isnumeric', 'isprintable', 'isspace',
'istitle', 'isupper', 'join', 'ljust',
'lower', 'lstrip', 'maketrans',
'partition', 'replace', 'rfind',
'rindex', 'rjust', 'rpartition',
'rsplit', 'rstrip', 'split',
'splitlines', 'startswith', 'strip',
'swapcase', 'title', 'translate',
'upper', 'zfill']
是的,在那里。既然这是一个方法,我们也可以称它为:
>>> "test".__len__()
4
这相当于len("test")但是少了很多优雅,所以不要这么做。这只是为了说明这东西是如何工作的。
还有一系列其他不那么神奇的方法向我们展示。随意尝试几个,比如islower:
>>> "test".islower()
True
该方法检查整个字符串是否是小写,如果是,那么 Python 返回布尔值True。其中一些方法需要一个或多个参数,如 replace:
>>> 'abcd'.replace('a', 'b')
'bbcd'
它用“b”替换所有出现的“a”。
Thank you for reading my tutorials. I write these in my free time, and it requires a lot of time and effort. I use ads to keep writing these free articles, I hope you understand! Support me by disabling your adblocker on my website or, alternatively, buy me some coffee. It's much appreciated and allows me to keep working on this site!
有时候编程可能有点像变魔术,尤其是当你刚刚开始的时候。但是一旦你在引擎盖下瞥了一眼,看到事情实际上是如何工作的,那种魔力就消失了。让我们继续来看看对象到底是什么,以及它们是如何定义的。
什么是 Python 对象?
既然我们已经使用了对象,并且知道 Python 中的一切都是对象,那么是时候定义什么是对象了:
Object
An object is a collection of data (variables) and methods that operate on that data. Objects are defined by a Python class.
对象和面向对象编程是 20 世纪 90 年代初开始流行的概念。早期的计算机语言,如 C,没有对象的概念。然而,事实证明,对于人类来说,对象是一种易于理解的范式。对象可以用来模拟现实生活中的许多概念和情况。如今,大多数(如果不是全部的话)新语言都有对象的概念。所以你将要学习的东西在概念上也适用于其他语言:这是基础计算机科学。
什么是 Python 类?
因为对象是 Python 语言的组成部分,所以您也可以自己创建对象。如果你想创建你自己类型的对象,你首先需要定义它的方法和它能保存什么数据。这个蓝图叫做类。
Class
A class is the blueprint for one or more objects
所有 Python 对象都基于一个类。当我们创建一个对象时,我们称之为“创建一个类的实例”。字符串、数字甚至布尔也是类的实例。让我们用内置函数type来探索一下:
>>> type('a')
<class 'str'>
>>> type(1)
<class 'int'>
type(True)
<class 'bool'>
显然,有被称为str、int和bool的类。这些是 Python 的一些原生类,但是,正如我所说的,我们也可以构建自己的类类型!
创建一个 Python 类
没有汽车类比的教程是不完整的,所以让我们创建一个代表汽车的 Python 类。要输入的内容很多,而且每一个错误都要重新开始。尽管试,但如果你想走捷径,我理解。只需将下面的类复制并粘贴到您的 Python REPL 中。粘贴后,确保按两次回车键:
class Car:
speed = 0
started = False
def start(self):
self.started = True
print("Car started, let's ride!")
def increase_speed(self, delta):
if self.started:
self.speed = self.speed + delta
print('Vrooooom!')
else:
print("You need to start the car first")
def stop(self):
self.speed = 0
print('Halting')
创建一个 Python 对象
不要担心,我们将一步一步地检查类定义,但是让我们首先创建并使用一个 Car 类型的 Python 对象:
>>> car = Car()
>>> car.increase_speed(10)
You need to start the car first
>>> car.start()
Car started, let's ride!
>>> car.increase_speed(40)
Vrooooom!
如果你愿意,你也可以使用下面的面包屑来玩我们新创建的汽车类:
https://crumb.sh/embed/GzaEerCX65E
Python 中的对象总是一个类的实例。一个类可以有许多实例。我们刚刚用Car()创建了类Car的一个实例,并将它赋给了(小写)变量car。创建一个实例看起来像调用一个函数;你以后会知道为什么。
接下来,我们调用我们的一个汽车对象方法:试图在它还没有启动的时候增加它的速度。哎呀!只有启动汽车后,我们才能提高它的速度,享受它发出的噪音。
现在让我们一步一步地复习我们的汽车课程:
- Python 中的类是使用 class 语句定义的,后跟类名(Car)。我们以冒号开始缩进的代码块。
- 我们定义了两个变量,速度和启动。这是该类的所有实例都将拥有的数据。
- 接下来,我们定义了三个操作变量的方法。
在这些方法的定义中,我们遇到了一些奇特的东西:它们都有一个名为 self 的参数作为它们的第一个参数。
Python 中的 self 是什么?
老实说,如果你问我的话,这是 Python 不太优雅的语言结构之一。
还记得我们调用 car 对象上的方法吗,比如car.start()?我们不必传递self变量,即使start()在类中被定义为start(self)。
事情是这样的:
- 当我们在 Python 对象上调用一个方法时,Python 会自动填充第一个变量,按照惯例我们称之为 self。
- 第一个变量是对对象本身的引用,因此得名。
- 我们可以用这个变量来引用这个对象的其他实例变量和函数,比如
self.speed和self.start()。
因此,只有在 Python 类定义内部,我们才使用self来引用作为实例一部分的变量。为了修改属于我们类的started变量,我们使用了self.started,而不仅仅是started。通过使用self,很明显我们操作的是这个实例中的一个变量,而不是在对象之外定义的、碰巧同名的其他变量。
创建多个 Python 对象
因为 Python 类只是一个蓝图,所以您可以用它来创建多个对象,就像您可以构建多辆外观相同的汽车一样。它们的行为都相似,但它们都有自己的数据,这些数据不在对象之间共享:
>>> car1 = Car()
>>> car2 = Car()
>>> id(car1)
139771129539104
>>> id(car2)
139771129539160
我们在这里创建了两个 car 对象,car1 和 car2,并使用内置方法 id()来获取它们的 id。Python 中的每个对象都有一个惟一的标识符,所以我们刚刚证明了我们从同一个类中创建了两个不同的对象。我们可以独立使用它们:
>>> car1.start()
Car started, let's ride!
>>> car1.increase_speed(10)
'Vrooom!'
>>> car1.speed
10
>>> car2.speed
0
我们刚刚启动了car1并提高了它的速度,而car2仍然处于暂停状态。对速度的检查证实了这些是不同状态的不同汽车!
继续学习
- 您可能也会对 Python 数据类感兴趣
- 如何从函数中返回多个值
- 关于课程的官方文件