当前位置: 首页 > 科技观察

您需要了解的更重要的Python概念

时间:2023-03-19 13:00:39 科技观察

Python易于学习。但是,它有一些困难的方面,例如类和对象的世界。在本文中,您将学习:在Python中,一切皆对象如何创建您自己的类和对象什么是继承以及如何利用它发挥您的优势通过揭开Python对象的神秘面纱,您对该语言的理解将大有帮助!对象对象在Python中起着核心作用。让我们来看看如何加深对主题的理解。在幕后,您可能知道内置的len函数。它返回你给它的对象的长度。但是,数字5的长度是多少?让我们问Python:>>>len(5)Traceback(mostrecentcalllast):File"",line1,inTypeError:objectoftype'int'hasnolen()我喜欢错误,因为它们说明了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__','大写','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此方法检查整个字符串是否为小写,因此Python返回布尔值True。其中一些方法采用一个或多个参数,例如replace:>>>'abcd'.replace('a','b')'bbcd'将所有出现的“a”替换为“b”。什么是对象既然我们已经使用过对象并且知道Python中的一切都是对象,那么是时候定义什么是对象了:对象是数据(变量)和操作该数据的方法的集合编程是一个在90年代初期流行的概念。像C这样的早期计算机语言没有对象的概念。然而,事实证明,对象是人类易于理解的范例——对于模拟许多现实世界的情况很有用。现在大多数(如果不是全部)新语言都有对象的概念。因此,您将学到的内容在概念上也适用于其他语言。由于对象是Python语言的基础,因此您也可以自己创建对象是合乎逻辑的。为此,我们需要先定义一个类。一个类如果要创建自己的对象类型,首先需要定义自己拥有的方法和可以容纳的数据。该蓝图称为类。类是对象的蓝图所有对象都基于类。当我们创建一个对象时,我们称之为“创建类的实例”。字符串、数字甚至布尔值也是类的实例。让我们探索内置函数类型:>>>type('a')>>>type(1)type(True)显然,有名为str、int和bool的类。这些是Python的一些原生类,但我们也可以构建自己的类!没有汽车类比的教程是不完整的,所以让我们创建一个类来表示汽车。需要输入的内容很多,您必须从头开始处理每一个错误。随意尝试,但如果你想走捷径,我理解。只需将以下内容复制并粘贴到您的PythonREPL中:classCar:speed=0started=Falsedefstart(self):self.started=Trueprint("Carstarted,let'sride!")defincrease_speed(self,delta):ifself。started:self.speed=self.speed+deltaprint('Vrooooom!')else:print("Youneedtostartthecarfirst")defstop(self):self.speed=0print('Halting')别担心,我们会继续的逐步,但首先创建并使用Car类型的对象:>>>car=Car()>>>car.increase_speed(10)您需要先启动汽车>>>car.start()汽车启动了,让我们骑!>>>car.increase_speed(40)Vrooooom!>>>_对象总是类的实例。一个类可以有很多实例。我们刚刚使用Car()创建了Car类的实例并将其分配给变量car。创建一个实例就像调用一个函数——稍后你会明白为什么。接下来,我们在汽车对象上调用一个方法:在它还没有启动时尝试提高它的速度。哎呀!只有在启动汽车后,我们才能加快速度并享受它发出的噪音。现在,让我们来看看汽车类:使用类语句后跟类名(Car)来定义类。我们缩进以冒号开头的代码块。我们定义了两个变量,speed和start。这是该类的所有实例都将拥有的数据。接下来,我们定义三个对变量进行操作的方法。在这些方法的定义中,我们遇到了一些奇怪的事情:它们都有一个名为self的参数作为它们的第一个参数。什么是自我?老实说,如果您问我,这是Python不太优雅的语言结构之一。还记得我们在car对象上调用方法,例如car.start()吗?即使start在类中定义为start(self),我们也不必传递self变量。事情是这样的:当我们调用一个对象的方法时,Python会自动填充第一个变量,我们习惯称它为self第一个变量是对对象本身的引用,所以它的名字我们可以用这个变量来使用引用对象的其他实例变量和函数,例如self.speed和self.start()。因此,只有在类定义内部,我们才使用self来引用属于实例的变量。要修改属于我们类一部分的开始变量,我们使用self.started而不是刚开始。通过使用self,我们可以清楚地看到我们在该实例上操作的变量,而不是在对象之外定义的恰好具有相同名称的其他变量。从一个类创建多个对象由于一个类只是一个蓝图,您可以使用它来创建多个对象,就像您可以制造多辆外观相同的汽车一样。它们的行为都相似,但它们都有自己的数据,这些数据不在对象之间共享:>>>car1=Car()>>>car2=Car()>>>id(car1)139771129539104>>>id(car2)139771129539160在这里,我们创建了两个汽车对象car1和car2,并使用内置方法id()获取它们的ID。Python中的每个对象都有一个唯一的标识符,所以我们只是证明我们从同一个类创建了两个不同的对象。我们可以独立使用它们:>>>car1.start()汽车启动了,让我们骑吧!>>>car1.increase_speed(10)'Vrooom!'>>>car1.speed10>>>car2.speed0我们刚刚启动了car1并在car2仍处于暂停状态时提高了速度。检查速度确认这些是具有不同状态的不同汽车!当构造函数从一个类创建一个对象时,看起来我们正在调用一个函数:car=Car()但我们实际上调用的不是函数,而是Function!我们不必定义的这种方法称为构造函数。它构造和初始化对象。默认情况下,每个类都有一个名为__init__的类,即使我们没有自己定义它。这与继承有关,您很快就会了解这一点。你用过str()函数将对象转换为类吗?或者将字符串转换为数字的int()函数?>>>'a'+str(1)'a1'>>>int('2')+24你实际上在这里做的是通过调用str和int类的构造函数创建str和int类型的新对象.我们还可以重写__init__方法,通过接受参数为其提供更多功能。让我们用自定义构造函数重新定义Car类:!")defincrease_speed(self,delta):ifself.started:self.speed=self.speed+deltaprint("Vrooooom!")else:print("Youneedtostartthecarfirst")defstop(self):self.speed=0us自定义构造函数for具有带默认值的命名参数,因此我们可以通过多种方式创建Car类的实例:>>>c1=Car()>>>c2=Car(True)>>>c3=Car(True,50)>>>c4=Car(started=True,speed=40)正如您可能已经注意到的,我们现在可以创建没有启动但速度仍然增加的新车。现在,让我们就此打住。继承在编程中,最好尽可能多地重用代码。这种做法甚至有一个很好的首字母缩写词,叫做DRY:不要重复自己。类可以帮助您避免重复代码,因为您可以编写一次类并基于它创建许多对象。但是,它们还以另一种方式帮助您,称为继承。类可以从其他类继承属性和函数,因此您不必重复您的工作。例如,我们希望Car类继承Vehicle类的一些基础知识。并且,在定义的同时,还定义了Motorcycle类。从示意图上看,它看起来像这样:>继承—作者提供的图片我们已经看到了继承的实际应用。还记得我告诉过你即使你不定义类,每个类都有一个构造函数(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类开始:classVehicle:def__init__(self,started=False,speed=0):self.started=startedself.speed=speeddefstart(self):self.started=Trueprint("开始,开始吧!")defstop(self):self.speed=0defincrease_speed(self,delta):ifself.started:self.speed=self.speed+deltaprint("Vrooooom!")else:print("Youneedtostartmefirst")现在,我们可以使用继承重新定义了我们的Car类:classCar(Vehicle):trunk_open=Falsedefopen_trunk(self):trunk_open=Truedefclose_trunk(self):trunk_open=False我们的car继承了Vehicle类的所有方法和变量,只是增加了一个额外的变量和两个方法操作后备箱。重写init方法有时你想重写init函数。为了演示,我们可以创建一个Motorcycle类。大多数摩托车都有一个中央支架。我们将添加放入或初始化它的能力:atall类的构造函数(我们从中继承)。如果您仍然需要该功能,则必须自己调用它。这是通过super()完成的:它返回对父类的引用,因此我们可以调用父类的构造函数。在这种情况下,我们添加了中心安装的功能,但删除了在构造函数中设置速度和启动状态的选项。如果需要,您还可以添加速度和启动状态选项,并将它们传递给Vehicle构造函数。覆盖其他方法就像__init__一样,我们也可以覆盖其他方法。比如你想实现一个不启动的摩托车,你可以重写start方法:):print("抱歉,没电了!")感谢阅读。如果您想了解有关Python的更多信息,请确保在https://python3.guide上查看我详尽的指南。