Python很容易学习。需解 但是比的,它具有某些难以理解的较重方面,例如类和对象的需解世界。 在本文中,比的您将学习: 通过使Python对象神秘化,您对语言的较重理解将大大增加! 对象 对象在Python中起着核心作用。 让我们来看看如何加深对主题的需解理解。 引擎盖下 您可能知道内置的比的len函数。 它返回您给它的较重对象的长度。 但是需解,数字五的比的长度是多少? 让我们问一下Python: >>> len(5) Traceback (most recent call last): File "", line 1, in TypeError: object of type int has no len() 我喜欢错误,服务器租用因为它们说明了Python在内部的较重工作方式。 在这种情况下,Python告诉我们5是一个对象,并且没有len()。 在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()的原因。 我在这里随便介绍了方法一词。 让我更正式地定义它: 当函数是对象的一部分时,我们称其为方法。 因此,如果字符串确实有长度,那么它必须具有__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"),但不够优雅。 所以不要这样做,只是为了说明这些东西是如何工作的。 dir()还向我们展示了其他一些不太神奇的方法。 随意尝试一些,例如islower: >>> "test".islower() True 此方法检查整个字符串是否为小写,云南idc服务商因此Python返回布尔值True。 其中一些方法需要一个或多个参数,例如replace: >>> abcd.replace(a, b) bbcd 它将所有出现的" a"替换为" b"。 什么是对象 现在我们已经使用了对象,并且知道Python中的所有内容都是对象,是时候定义什么是对象了: 对象是数据(变量)的集合以及对该数据进行操作的方法 对象和面向对象的编程是在1990年代初期流行的概念。 像C这样的早期计算机语言没有对象的概念。 但是,事实证明,对象是人类易于理解的范例-可用于对许多现实情况进行建模。 如今,大多数(如果不是全部)新语言都具有对象的概念。 因此,您将要学习的内容在概念上也将适用于其他语言。 由于对象是Python语言的基础,因此您也可以自己创建对象,这是合乎逻辑的。 为此,我们需要首先定义一个类。 类 如果要创建自己的对象类型,则首先需要定义它具有的方法和可以容纳的数据。 该蓝图称为类。 类是对象的蓝图 所有对象都基于一个类。 创建对象时,我们将其称为"创建类的实例"。 字符串,数字甚至布尔值也是类的实例。 让我们探索一下内置函数类型: >>> type(a) >>> type(1) type(True) 显然,有一些类叫做str,int和bool。 这些是Python的一些本机类,但我们也可以构建自己的类! 如果没有汽车的类比,那么没有一部教程是完整的,因此让我们创建一个代表汽车的类。 输入的内容很多,您必须重新开始每个错误。 随时尝试,但是如果您想走捷径,我了解。 只需将以下内容复制并粘贴到您的Python REPL中: 不用担心,我们将逐步进行介绍,但首先创建并使用Car类型的对象: >>> car = Car() >>> car.increase_speed(10) You need to start the car first >>> car.start() Car started, lets ride! >>> car.increase_speed(40) Vrooooom! >>> _ 对象始终是类的实例。 一类可以有许多实例。 我们只是使用Car()创建了Car类的实例,并将其分配给可变car。 创建实例就像调用函数一样-稍后将了解原因。 接下来,我们在汽车对象上调用一种方法:尝试在尚未启动时提高其速度。 糟糕! 只有在启动汽车后,我们才能提高速度并享受它发出的噪音。 现在,让我们逐步了解一下汽车课: 在这些方法的定义中,我们遇到了一些奇怪的事情:它们都有一个名为self的参数作为它们的第一个参数。 什么是Self? 老实说,如果您问我,这是Python不太优雅的语言构造之一。 还记得我们在调用car对象上的方法时,例如car.start()吗? 即使start被定义为类中的start(self),我们也不必传递self变量。 这是正在发生的事情: 因此,仅在类定义内部,我们才使用self来引用属于实例的变量。 要修改属于我们课程一部分的开始变量,我们使用self.started而不是仅仅启动。 通过使用self,我们可以很清楚地了解到我们正在对该实例进行操作的变量,而不是在对象外部定义且碰巧具有相同名称的其他变量。 从一个类创建多个对象 由于类只是一个蓝图,因此您可以使用它来创建多个对象,就像可以制造多个外观相同的汽车一样。 它们的行为都相似,但是它们都有自己的数据,这些数据不会在对象之间共享: >>> car1 = Car() >>> car2 = Car() >>> id(car1) 139771129539104 >>> id(car2) 139771129539160 我们在这里创建了两个car对象car1和car2,并使用内置方法id()来获取它们的id。 Python中的每个对象都有一个唯一的标识符,因此我们只是证明我们从同一类创建了两个不同的对象。 我们可以独立使用它们: >>> car1.start() Car started, lets ride! >>> car1.increase_speed(10) Vrooom! >>> car1.speed 10 >>> car2.speed 0 我们刚刚启动了car1并提高了速度,而car2仍然暂停。 检查速度可以确认这是状态不同的不同汽车! 构造函数 从类创建对象时,看起来我们正在调用一个函数: car = Car() 但这不只是看起来像我们在调用函数,实际上是在调用函数! 我们不必定义的此方法称为构造函数。 它构造并初始化对象。 默认情况下,每个类都有一个名为__init__的类,即使我们自己没有定义它。 这与继承有关,您将很快了解。 您是否曾经使用过str()函数将对象转换为类? 还是int()函数将字符串转换为数字? >>> a + str(1) a1 >>> int(2) + 2 4 您实际上在这里所做的就是通过调用str和int类的构造函数来创建类型为str和int的新对象。 我们也可以重写__init__方法,以通过接受参数来赋予它更多的功能。 让我们使用自定义构造函数重新定义Car类: 我们的自定义构造函数已使用默认值命名参数,因此我们可以通过多种方式创建Car类的实例: >>> c1 = Car() >>> c2 = Car(True) >>> c3 = Car(True, 50) >>> c4 = Car(started=True, speed=40) 您可能已经注意到,我们现在可以创建未启动但仍要提高速度的新车。 现在,让我们就这样了。 继承 在编程中,最好重用尽可能多的代码。 这种做法甚至有一个很好的缩写,叫做DRY:不要重复自己。 类可以帮助您避免重复代码,因为您可以编写一次类并根据该类创建许多对象。 但是,它们还以另一种方式(称为继承)帮助您。 类可以继承其他类的属性和函数,因此您不必重复自己的工作。 举例来说,我们希望Car类继承Vehicle类的一些基础知识。 并且,在定义的同时,还定义了Motorcycle类。 从示意图上看,它看起来像这样: > Inheritance — image by author 我们已经看到继承在起作用。 还记得我曾告诉您,即使您没有定义一个类,每个类都有一个构造函数(init)吗? 这是因为每个类都继承自Python中最基础的类,即object: >>> dir(object) [__class__, __delattr__, __dir__, __doc__, __eq__, __format__, __ge__, __getattribute__, __gt__, __hash__, __init__, __init_subclass__, __le__, __lt__, __ne__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __sizeof__, __str__, __subclasshook__] 当我告诉您" Python中的一切都是对象"时,我的意思就是一切。 这包括类,并且您可以看到我们也可以在类上使用dir()。 它表明该对象具有__init__方法。 不错,不是吗? 继承映射到许多现实情况。 根据上图,我们来看看继承的作用。 我们将从通用的Vehicle类开始: 现在,我们可以使用继承重新定义我们的Car类: 我们的汽车继承了Vehicle类的所有方法和变量,但添加了一个额外的变量和两个方法来操作后备箱。 覆盖init方法 有时您想覆盖init函数。 为了演示,我们可以创建一个Motorcycle类。 大多数摩托车都有中央支架。 我们将添加将其放入或初始化的功能: 当您重写构造函数时,根本不会调用父类(我们从中继承)的构造函数。 如果仍然需要该功能,则必须自己调用它。 这是通过super()完成的:它返回对父类的引用,因此我们可以调用父类的构造函数。 在这种情况下,我们增加了中置支架的功能,但删除了在构造函数中设置速度和启动状态的选项。 如果需要,您也可以添加速度和启动状态选项,并将其传递给Vehicle构造函数。 覆盖其他方法 就像__init__一样,我们也可以覆盖其他方法。 例如,如果您要实施不启动的摩托车,则可以覆盖启动方法: 感谢您的阅读。 如果您想了解有关Python的更多信息,请确保在https://python3.guide上查看我的详尽指南。