https://m.toutiao.com/is/JEmD36X/ 了解有關Python語言構建模塊的所有信息 > Image by author Python很容易學習,。 但是,,它具有某些難以理解的方面,,例如類和對象的世界,。 在本文中,,您將學習: · 在Python中,,一切都是對象 · 如何創(chuàng)建自己的類和對象 · 什么是繼承,,以及如何利用它來發(fā)揮自己的優(yōu)勢 通過使Python對象神秘化,,您對語言的理解將大大增加! 對象對象在Python中起著核心作用。 讓我們來看看如何加深對主題的理解,。 引擎蓋下您可能知道內置的len函數(shù),。 它返回您給它的對象的長度。 但是,,數(shù)字五的長度是多少,? 讓我們問一下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是一個對象,并且沒有l(wèi)en(),。 在Python中,,一切都是對象。 字符串,,布爾值,,數(shù)字甚至函數(shù)都是對象。 我們可以使用內置函數(shù)dir()檢查REPL中的對象,。 當我們在數(shù)字5上嘗試dir時,,它將顯示出一個包含在任何數(shù)字對象中的函數(shù)的大列表: >>> 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'] 為了清楚起見,我將列表略去了一些,。 該列表以這些帶有下劃線的怪異命名函數(shù)開頭,,例如__add__。 這些方法稱為魔術方法或dunder(雙下劃線的縮寫)方法,。 如果仔細觀察,,您會發(fā)現(xiàn)int類型的對象沒有__len__ dunder方法。 這就是Python的len()函數(shù)如何知道數(shù)字沒有長度的原因,。 len()所做的全部工作就是在提供它的對象上調用__len __()方法,。 這也是為什么Python抱怨' int'類型的對象沒有l(wèi)en()的原因。 我在這里隨便介紹了方法一詞,。 讓我更正式地定義它: 當函數(shù)是對象的一部分時,,我們稱其為方法。 因此,,如果字符串確實有長度,,那么它必須具有__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'),,但不夠優(yōu)雅。 所以不要這樣做,,只是為了說明這些東西是如何工作的,。 dir()還向我們展示了其他一些不太神奇的方法。 隨意嘗試一些,,例如islower: >>> 'test'.islower() True 此方法檢查整個字符串是否為小寫,,因此Python返回布爾值True。 其中一些方法需要一個或多個參數(shù),,例如replace: >>> 'abcd'.replace('a', 'b') 'bbcd' 它將所有出現(xiàn)的' a'替換為' b',。 什么是對象現(xiàn)在我們已經(jīng)使用了對象,并且知道Python中的所有內容都是對象,,是時候定義什么是對象了: 對象是數(shù)據(jù)(變量)的集合以及對該數(shù)據(jù)進行操作的方法 對象和面向對象的編程是在1990年代初期流行的概念,。 像C這樣的早期計算機語言沒有對象的概念。 但是,,事實證明,,對象是人類易于理解的范例-可用于對許多現(xiàn)實情況進行建模。 如今,,大多數(shù)(如果不是全部)新語言都具有對象的概念,。 因此,您將要學習的內容在概念上也將適用于其他語言,。 由于對象是Python語言的基礎,,因此您也可以自己創(chuàng)建對象,這是合乎邏輯的,。 為此,,我們需要首先定義一個類。 類如果要創(chuàng)建自己的對象類型,,則首先需要定義它具有的方法和可以容納的數(shù)據(jù),。 該藍圖稱為類。 類是對象的藍圖 所有對象都基于一個類,。 創(chuàng)建對象時,,我們將其稱為'創(chuàng)建類的實例'。 字符串,,數(shù)字甚至布爾值也是類的實例,。 讓我們探索一下內置函數(shù)類型: >>> type('a') <class 'str'> >>> type(1) <class 'int'> type(True) <class 'bool'> 顯然,有一些類叫做str,,int和bool,。 這些是Python的一些本機類,但我們也可以構建自己的類,! 如果沒有汽車的類比,那么沒有一部教程是完整的,因此讓我們創(chuàng)建一個代表汽車的類,。 輸入的內容很多,,您必須重新開始每個錯誤。 隨時嘗試,,但是如果您想走捷徑,,我了解。 只需將以下內容復制并粘貼到您的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') 不用擔心,,我們將逐步進行介紹,,但首先創(chuàng)建并使用Car類型的對象: >>> 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! >>> _ 對象始終是類的實例。 一類可以有許多實例,。 我們只是使用Car()創(chuàng)建了Car類的實例,,并將其分配給可變car。 創(chuàng)建實例就像調用函數(shù)一樣-稍后將了解原因,。 接下來,,我們在汽車對象上調用一種方法:嘗試在尚未啟動時提高其速度。 糟糕,! 只有在啟動汽車后,,我們才能提高速度并享受它發(fā)出的噪音。 現(xiàn)在,,讓我們逐步了解一下汽車課: · 使用class語句后跟類名(Car)定義類,。 我們從冒號開始縮進代碼塊。 · 我們定義了兩個變量,,速度和開始,。 這是此類的所有實例將具有的數(shù)據(jù)。 · 接下來,,我們定義了對變量進行操作的三種方法,。 在這些方法的定義中,我們遇到了一些奇怪的事情:它們都有一個名為self的參數(shù)作為它們的第一個參數(shù),。 什么是Self,?老實說,如果您問我,,這是Python不太優(yōu)雅的語言構造之一,。 還記得我們在調用car對象上的方法時,例如car.start()嗎,? 即使start被定義為類中的start(self),,我們也不必傳遞self變量。 這是正在發(fā)生的事情: · 當我們在對象上調用方法時,,Python會自動填充第一個變量,,我們習慣將其稱為self · 第一個變量是對對象本身的引用,,因此它的名稱 · 我們可以使用此變量來引用該對象的其他實例變量和函數(shù),例如self.speed和self.start(),。 因此,,僅在類定義內部,我們才使用self來引用屬于實例的變量,。 要修改屬于我們課程一部分的開始變量,,我們使用self.started而不是僅僅啟動。 通過使用self,,我們可以很清楚地了解到我們正在對該實例進行操作的變量,,而不是在對象外部定義且碰巧具有相同名稱的其他變量。 從一個類創(chuàng)建多個對象由于類只是一個藍圖,,因此您可以使用它來創(chuàng)建多個對象,,就像可以制造多個外觀相同的汽車一樣。 它們的行為都相似,,但是它們都有自己的數(shù)據(jù),,這些數(shù)據(jù)不會在對象之間共享: >>> car1 = Car() >>> car2 = Car() >>> id(car1) 139771129539104 >>> id(car2) 139771129539160 我們在這里創(chuàng)建了兩個car對象car1和car2,并使用內置方法id()來獲取它們的id,。 Python中的每個對象都有一個唯一的標識符,,因此我們只是證明我們從同一類創(chuàng)建了兩個不同的對象。 我們可以獨立使用它們: >>> car1.start() Car started, let's ride! >>> car1.increase_speed(10) 'Vrooom!' >>> car1.speed 10 >>> car2.speed 0 我們剛剛啟動了car1并提高了速度,,而car2仍然暫停,。 檢查速度可以確認這是狀態(tài)不同的不同汽車! 構造函數(shù)從類創(chuàng)建對象時,,看起來我們正在調用一個函數(shù): car = Car() 但這不只是看起來像我們在調用函數(shù),,實際上是在調用函數(shù)! 我們不必定義的此方法稱為構造函數(shù),。 它構造并初始化對象,。 默認情況下,每個類都有一個名為__init__的類,,即使我們自己沒有定義它,。 這與繼承有關,您將很快了解,。 您是否曾經(jīng)使用過str()函數(shù)將對象轉換為類,? 還是int()函數(shù)將字符串轉換為數(shù)字? >>> 'a' + str(1) 'a1' >>> int('2') + 2 4 您實際上在這里所做的就是通過調用str和int類的構造函數(shù)來創(chuàng)建類型為str和int的新對象,。 我們也可以重寫__init__方法,,以通過接受參數(shù)來賦予它更多的功能。 讓我們使用自定義構造函數(shù)重新定義Car類: class Car: def __init__(self, started = False, speed = 0): self.started = started self.speed = speed 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 我們的自定義構造函數(shù)已使用默認值命名參數(shù),,因此我們可以通過多種方式創(chuàng)建Car類的實例: >>> c1 = Car() >>> c2 = Car(True) >>> c3 = Car(True, 50) >>> c4 = Car(started=True, speed=40) 您可能已經(jīng)注意到,,我們現(xiàn)在可以創(chuàng)建未啟動但仍要提高速度的新車,。 現(xiàn)在,讓我們就這樣了,。 繼承在編程中,,最好重用盡可能多的代碼。 這種做法甚至有一個很好的縮寫,,叫做DRY:不要重復自己。 類可以幫助您避免重復代碼,,因為您可以編寫一次類并根據(jù)該類創(chuàng)建許多對象,。 但是,它們還以另一種方式(稱為繼承)幫助您,。 類可以繼承其他類的屬性和函數(shù),,因此您不必重復自己的工作。 舉例來說,,我們希望Car類繼承Vehicle類的一些基礎知識,。 并且,在定義的同時,,還定義了Motorcycle類,。 從示意圖上看,它看起來像這樣: > Inheritance — image by author 我們已經(jīng)看到繼承在起作用,。 還記得我曾告訴您,,即使您沒有定義一個類,每個類都有一個構造函數(shù)(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__方法,。 不錯,,不是嗎? 繼承映射到許多現(xiàn)實情況,。 根據(jù)上圖,,我們來看看繼承的作用。 我們將從通用的Vehicle類開始: class Vehicle: def __init__(self, started = False, speed = 0): self.started = started self.speed = speed def start(self): self.started = True print('Started, let's ride!') def stop(self): self.speed = 0 def increase_speed(self, delta): if self.started: self.speed = self.speed + delta print('Vrooooom!') else: print('You need to start me first') 現(xiàn)在,,我們可以使用繼承重新定義我們的Car類: class Car(Vehicle): trunk_open = False def open_trunk(self): trunk_open = True def close_trunk(self): trunk_open = False 我們的汽車繼承了Vehicle類的所有方法和變量,,但添加了一個額外的變量和兩個方法來操作后備箱。 覆蓋init方法有時您想覆蓋init函數(shù),。 為了演示,,我們可以創(chuàng)建一個Motorcycle類,。 大多數(shù)摩托車都有中央支架。 我們將添加將其放入或初始化的功能: class Motorcycle(Vehicle): def __init__(self, center_stand_out = False): self.center_stand_out = center_stand_out super().__init__() 當您重寫構造函數(shù)時,,根本不會調用父類(我們從中繼承)的構造函數(shù),。 如果仍然需要該功能,則必須自己調用它,。 這是通過super()完成的:它返回對父類的引用,,因此我們可以調用父類的構造函數(shù)。 在這種情況下,,我們增加了中置支架的功能,,但刪除了在構造函數(shù)中設置速度和啟動狀態(tài)的選項。 如果需要,,您也可以添加速度和啟動狀態(tài)選項,,并將其傳遞給Vehicle構造函數(shù)。 覆蓋其他方法就像__init__一樣,,我們也可以覆蓋其他方法,。 例如,如果您要實施不啟動的摩托車,,則可以覆蓋啟動方法: class Motorcycle(Vehicle): def __init__(self, center_stand_out = False): self.center_stand_out = center_stand_out super().__init__() def start(self): print('Sorry, out of fuel!') 感謝您的閱讀,。 如果您想了解有關Python的更多信息,請確保在https://ide上查看我的詳盡指南,。 (本文翻譯自Erik van Baaren的文章《The Most Important Python Concept That You Need to Understand》,,參考:https:///the-most-important-python-concept-that-you-need-to-understand-985b98bbb84) |
|
來自: 山峰云繞 > 《Python代碼知識游戲黑客編程與英語》