深入了解Python的類與模塊化
學(xué)習(xí)目標(biāo)
Python 是簡(jiǎn)潔、易學(xué)、面向?qū)ο蟮木幊陶Z(yǔ)言。它不僅擁有強(qiáng)大的原生數(shù)據(jù)類型,也提供了簡(jiǎn)單易用的控制語(yǔ)句。本節(jié)的主要目標(biāo)是介紹 Python 中的面向?qū)ο缶幊谭妒揭约澳K化思想,為接下來(lái)的學(xué)習(xí)奠定基礎(chǔ),本文會(huì)完整的介紹學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)和算法所需的 Python 基礎(chǔ)知識(shí)及基本思想,并給出相應(yīng)的實(shí)戰(zhàn)示例及解釋。
掌握 Python 面向?qū)ο缶幊痰幕靖拍睿?huì)編寫(xiě) Python 自定義類
掌握 Python 模塊化的編程思想
1. 面向?qū)ο缶幊蹋侯?/h2>
1.1 面向?qū)ο缶幊痰幕靖拍?/h3>
一個(gè)完善的程序是由數(shù)據(jù)和指令組成的。過(guò)程式編程利用“分而治之”的思想,使用函數(shù)對(duì)數(shù)據(jù)進(jìn)行處理,數(shù)據(jù)與函數(shù)之前的關(guān)系是松散的,即同樣的數(shù)據(jù)可以被程序中的所有函數(shù)訪問(wèn),而一個(gè)函數(shù)也可以訪問(wèn)程序中的不同數(shù)據(jù)。這導(dǎo)致了,如果出現(xiàn)異常,需要在整個(gè)系統(tǒng)中查找錯(cuò)誤代碼。
為了解決這一問(wèn)題,面向?qū)ο缶幊?(Object Oriented Programming, OOP) 將系統(tǒng)劃分為不同對(duì)象,每個(gè)對(duì)象包含自身的信息數(shù)據(jù)以及操作這些數(shù)據(jù)的方法。例如,每個(gè)字符串對(duì)象具有字符數(shù)據(jù),同時(shí)還具有改變大小寫(xiě)、查找等方法。
面向?qū)ο缶幊淌褂妙惷枋銎渌乃袑?duì)象的共同特性(屬性),即數(shù)據(jù)屬性(也稱數(shù)據(jù)成員或成員變量)和功能屬性(也稱成員函數(shù)或方法)。
一個(gè)類的對(duì)象也稱為這個(gè)類的一個(gè)實(shí)例。例如,32 就是一個(gè)整數(shù)類 int 的對(duì)象,可以使用函數(shù) type()
來(lái)獲取對(duì)象所屬類:
>>> type(32) <class 'int'>
可以利用內(nèi)置函數(shù) dir()
查詢類的屬性:
>>> dir(32) ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
在繼續(xù)講解之前,我們首先來(lái)快速介紹下面向?qū)ο蟮娜筇匦浴鄳B(tài)、封裝和繼承。
1.1.1 多態(tài)
多態(tài):可對(duì)不同類型的對(duì)象執(zhí)行相同的操作。
多態(tài)其實(shí)很常見(jiàn),例如列表對(duì)象和元組對(duì)象都具有 count
方法,使用變量調(diào)用 count
方法時(shí),我們無(wú)需知道它究竟是列表還是元組,這就是多態(tài)的作用。這不僅僅適用于方法,許多內(nèi)置運(yùn)算符和函數(shù)也使用了多態(tài):
>>> [1,3,3,3].count(3) 3 >>> (1,3,3,3).count(3) 3 >>> [1,3]+[1,3] [1, 3, 1, 3] >>> 'hello' + ' world!' 'hello world!'
1.1.2 封裝
封裝:對(duì)外部隱藏有關(guān)對(duì)象具體操作的細(xì)節(jié)。
封裝與多態(tài)類似,都屬于抽象原則,都用于處理程序的組成部分而無(wú)需關(guān)心不必要的細(xì)節(jié),但不同的是,多態(tài)使我們無(wú)需知道對(duì)象所屬的類就能調(diào)用其方法,而封裝使我們無(wú)需知道對(duì)象的內(nèi)部構(gòu)造就能使用它。例如我們將虛數(shù)的實(shí)部和虛部作為對(duì)象的數(shù)據(jù)屬性,就是將對(duì)象的屬性“封裝”在對(duì)象中。
1.1.3 繼承
繼承:用于建立類的層次結(jié)構(gòu),基于上層的類創(chuàng)建出新類。
如果我們有了一些類,再創(chuàng)建新的類時(shí)發(fā)現(xiàn)與已存在的類十分相似,只需要添加一些新方法,那么我們可能不想復(fù)制舊類的代碼至新類中,這時(shí)我們就要用到繼承了。例如,我們有了一個(gè) Fruit
類,具有描述外觀的方法 show_shape
,如果想要新建一個(gè) Apple
類,除了描述外觀外,我們還想知道如何計(jì)算總價(jià),那么我們就可以讓 Apple
類繼承 Fruit
的方法,使得對(duì) Apple
對(duì)象調(diào)用方法 show_shape
時(shí),將自動(dòng)調(diào)用 Fruit
類的這個(gè)方法。
1.2 自定義類
我們已經(jīng)知道抽象數(shù)據(jù)類型就是一個(gè)由對(duì)象以及對(duì)象上的操作組成的集合,對(duì)象和操作被捆綁為一個(gè)整體,不但可以使用對(duì)象的數(shù)據(jù)屬性,還可以使用對(duì)象上的操作。操作(在類中稱為方法)定義了抽象數(shù)據(jù)類型和程序其他部分之間的接口。接口定義了操作要做什么,但沒(méi)有說(shuō)明如何做,因此我們可以說(shuō)抽象的根本目標(biāo)是隱藏操作的細(xì)節(jié)。而類就是為了實(shí)現(xiàn)數(shù)據(jù)抽象類型。
Python 用關(guān)鍵字 class
定義一個(gè)類,格式如下,其中方法定義與函數(shù)定義語(yǔ)法類似:
class 類名:
方法定義
接下來(lái)構(gòu)建實(shí)現(xiàn)抽象數(shù)據(jù)類型 Imaginary
(虛數(shù))的類,用于展示如何實(shí)現(xiàn)自定義類。
定義類時(shí)首先需要提供構(gòu)造方法,構(gòu)造方法定義了數(shù)據(jù)對(duì)象的創(chuàng)建方式。要?jiǎng)?chuàng)建一個(gè) Imaginary
對(duì)象,需要提供實(shí)部和虛部?jī)刹糠謹(jǐn)?shù)據(jù),Python 中,__init__()
作為構(gòu)造方法名:
class Imaginary: def __init__(self, real, imag): self.real = real self.imag = imag
形式參數(shù)列表的第一項(xiàng)是一個(gè)指向?qū)ο蟊旧淼奶厥鈪?shù)(習(xí)慣上通常使用 self
),在調(diào)用時(shí)不需要提供相應(yīng)的實(shí)際參數(shù),而構(gòu)造方法中的剩余參數(shù)必須提供相應(yīng)的實(shí)參,使得新創(chuàng)建的對(duì)象能夠知道其初始值,與函數(shù)定義一樣,可以通過(guò)默認(rèn)值為形參提供默認(rèn)實(shí)參。如在 Imaginary
類中,self.real
定義了 Imaginary
對(duì)象有一個(gè)名為 real
的內(nèi)部數(shù)據(jù)對(duì)象作為其實(shí)部數(shù)據(jù)屬性,而self.imag
則定義了虛部。
創(chuàng)建 Imaginary
類的實(shí)例時(shí),會(huì)調(diào)用類中定義的構(gòu)造方法,使用類名并且傳入數(shù)據(jù)屬性的實(shí)際值完成調(diào)用:
>>> imaginary_a = Imaginary(6, 6) >>> imaginary_a <__main__.Imaginary object at 0x0000020CF1B80160>
以上代碼創(chuàng)建了一個(gè)對(duì)象,名為 imaginary_a
,值為 6+6i,這就是封裝的示例,將數(shù)據(jù)屬性和操作數(shù)據(jù)屬性的方法打包在對(duì)象中。
除了實(shí)例化外,類還支持另一操作:屬性引用(包括數(shù)據(jù)屬性和功能屬性),通過(guò)點(diǎn)標(biāo)記法訪問(wèn)與類關(guān)聯(lián)的屬性:
>>> imaginary_a.real 6 >>> imaginary_a.imag 6
除了數(shù)據(jù)屬性外,還需要實(shí)現(xiàn)抽象數(shù)據(jù)類型所需要的方法(功能屬性),需要牢記的是,方法的第一個(gè)參數(shù) self
是必不可少的,例如要實(shí)現(xiàn)打印實(shí)例化的虛數(shù)對(duì)象,編寫(xiě)類方法 display()
:
class Imaginary: def __init__(self, real, imag): self.real = real self.imag = imag def display(self): print('{}{:+}i'.format(self.real, self.imag))
調(diào)用類方法打印實(shí)例化的虛數(shù)對(duì)象:
>>> imaginary_a = Imaginary(6, 6) >>> imaginary_a.display() 6+6i >>> print(imaginary_a) <__main__.Imaginary object at 0x0000020CF1B72D90>
可以看到,如果使用 print()
函數(shù)只能打印存儲(chǔ)在變量中的地址,這是由于將對(duì)象轉(zhuǎn)換成字符串的方法 __str__()
的默認(rèn)實(shí)現(xiàn)是返回實(shí)例的地址字符串,如果想要使用 print
函數(shù)打印對(duì)象,需要重寫(xiě)默認(rèn)的 __str__()
方法,或者說(shuō)重載該方法:
>>> imaginary_a = Imaginary(6, 6) >>> imaginary_a.display() 6+6i >>> print(imaginary_a) <__main__.Imaginary object at 0x0000020CF1B72D90>
此時(shí)如果再次使用 print()
函數(shù),就可以直接打印對(duì)象了:
>>> imaginary_a = Imaginary(6, 6) >>> print(imaginary_a) 6+6i
可以重載類中的很多方法,最常見(jiàn)的是重載運(yùn)算符,這是由于人們習(xí)慣使用熟悉的運(yùn)算符對(duì)數(shù)據(jù)進(jìn)行運(yùn)算,這要比使用函數(shù)對(duì)數(shù)據(jù)進(jìn)行運(yùn)算更加直觀且易于理解,如表達(dá)式:8 + 6 / 3,如果用函數(shù)則為:add(8, div(6, 3)),顯然前者比后者更加符合習(xí)慣。 如果某種類型的對(duì)象要使用常見(jiàn)運(yùn)算符,就必須對(duì)這種類型重新定義相應(yīng)的運(yùn)算符函數(shù),例如,Python 對(duì)于 int 整型、float 浮點(diǎn)型、str 字符串類型等都重新定義了乘法運(yùn)算符函數(shù),對(duì)一個(gè)類型重新定義運(yùn)算符函數(shù)的也稱“運(yùn)算符重載”。我們可以編寫(xiě) Imaginary
類的 __mul__()
方法重載乘法運(yùn)算:
class Imaginary: def __init__(self, real, imag): self.real = real self.imag = imag def display(self): print('{}{:+}i'.format(self.real, self.imag)) def __str__(self): print('{}{:+}i'.format(self.real, self.imag)) def __mul__(self, other): new_real = self.real * other.real - self.imag * other.imag new_imag = self.real * other.imag + self.imag * other.real return Imaginary(new_real, new_imag)
還可以重載其他運(yùn)算符,如比較運(yùn)算符 ==,即 __eq__()
方法,重載 Imaginary
類的 __eq__()
方法允許兩個(gè)虛數(shù)進(jìn)行比較,查看它們的值是否相等,這也稱為深相等;而根據(jù)引用進(jìn)行判斷的淺相等,只有兩個(gè)變量是同一個(gè)對(duì)象的引用時(shí)才相等:
# shallow_and_deep_equal.py class ImaginaryFirst: def __init__(self, real, imag): self.real = real self.imag = imag def display(self): print('{}{:+}i'.format(self.real, self.imag)) def __str__(self): print('{}{:+}i'.format(self.real, self.imag)) class Imaginary: def __init__(self, real, imag): self.real = real self.imag = imag def display(self): print('{}{:+}i'.format(self.real, self.imag)) def __str__(self): print('{}{:+}i'.format(self.real, self.imag)) def __eq__(self, other): return self.real == other.real and self.imag == self.imag print('淺相等:只有兩個(gè)變量是同一個(gè)對(duì)象的引用時(shí)才相等。') imag_1 = imag_2 = ImaginaryFirst(6, 6) print('imag_1 == imag_2 ', imag_1 == imag_2) imag_1 = ImaginaryFirst(6, 6) imag_2 = ImaginaryFirst(6, 6) print('imag_1 == imag_2 ', imag_1 == imag_2) print('深相等:兩個(gè)變量的值相等即表示對(duì)象相等。') imag_1 = imag_2 = Imaginary(6, 6) print('imag_1 == imag_2 ', imag_1 == imag_2) imag_1 = Imaginary(6, 6) imag_2 = Imaginary(6, 6) print('imag_1 == imag_2 ', imag_1 == imag_2)
程序運(yùn)行結(jié)果如下所示:
淺相等:只有兩個(gè)變量是同一個(gè)對(duì)象的引用時(shí)才相等。
imag_1 == imag_2? ?True
imag_1 == imag_2? ?False
深相等:兩個(gè)變量的值相等即表示對(duì)象相等。
imag_1 == imag_2? ?True
imag_1 == imag_2? ?True
1.3 再談繼承
1.3.1 繼承實(shí)例
繼承可以建立一組彼此相關(guān)的抽象,能夠建立一個(gè)類的層次結(jié)構(gòu),這樣的關(guān)系結(jié)構(gòu)也稱為繼承層次結(jié)構(gòu),每個(gè)類都可以從上層的類繼承屬性。在 Python 中,object
類位于最頂層。
下層的新類會(huì)繼承已有類的屬性,同時(shí)添加自己特有的一些屬性,這個(gè)新的類就稱為“派生類”或“子類”,而原有的類稱為“基類”、“父類”或“超類”。利用父類定義子類,需要在定義的類名后添加圓括號(hào),圓括號(hào)內(nèi)寫(xiě)入父類名。如果沒(méi)有顯式地說(shuō)明一個(gè)類的父類,則默認(rèn)其父類為 object
。
例如三角形,包括銳角三角形、直角三角形和鈍角三角形,因此定義類時(shí),除了定義一般三角形的類 Triangle
外,還可以定義銳角三角形的類 AcuteTriangle
等,這時(shí)我們就可以令 AcuteTriangle
類繼承 Triangle
類:
class Triangle: def __init__(self, edge_1, edge_2, edge_3): self.edge_1 = edge_1 self.edge_2 = edge_2 self.edge_3 = edge_3 def __str__(self): return str((self.edge_1, self.edge_2, self.edge_3)) def print_info(self): print('The three sides of a triangle are {}, {} and {}'.format(self.edge_1, self.edge_2, self.edge_3)) def perimeter(self): return self.edge_1 + self.edge_2 + self.edge_3 class AcuteTriangle(Triangle): def __init__(self, edge_1, edge_2, edge_3, max_angle): # 使用父類構(gòu)造函數(shù)進(jìn)行初始化 Triangle.__init__(self, edge_1, edge_2, edge_3) self.max_angle = max_angle def print_info(self): Triangle.print_info(self) print('The max angle is {}'.format(self.max_angle)) def get_max_angle(self): return self.max_angle
可以看到子類除了繼承外,還可以:
- 添加新屬性,例如子類
AcuteTriangle
中新增了數(shù)據(jù)屬性max_angle
以及方法屬性get_max_angle
; - 替換(覆蓋)父類中的屬性,例如AcuteTriangle覆蓋了父類的__init__()和
print_info()
方法。以AcuteTriangle.__init__()
方法為例,首先調(diào)用Triangle.__init__()
初始化被繼承的實(shí)例變量 self.edge_1,self.edge_2,self.edge_3, 然后初始化self.max_angle
,這個(gè)實(shí)例變量只在AcuteTriangle
實(shí)例中才有,而Triangle
實(shí)例中沒(méi)有。
>>> triangle_a = Triangle(3, 4, 6) >>> triangle_a.print_info() The three sides of a triangle are 3, 4 and 6 >>> triangle_b = AcuteTriangle(3, 3, 3, 60) >>> triangle_b.print_info() The three sides of a triangle are 3, 3 and 3 The max angle is 60
在子類中可以通過(guò) super()
方法來(lái)調(diào)用父類的方法,這種方法可以省略父類名:
class AcuteTriangle(Triangle): def __init__(self, edge_1, edge_2, edge_3, max_angle): # 使用父類構(gòu)造函數(shù)進(jìn)行初始化 super().__init__(self, edge_1, edge_2, edge_3) self.max_angle = max_angle def print_info(self): super().print_info(self) print('The max angle is {}'.format(self.max_angle)) def get_max_angle(self): return self.max_angle
使用內(nèi)置函數(shù) isinstance()
可以檢查一個(gè)對(duì)象是否是某個(gè)類的實(shí)例(對(duì)象),而要確定一個(gè)類是否是另一個(gè)類的子類,則可以使用內(nèi)置方法 issubclass()
:
>>> triangle_a = Triangle(3, 4, 6) >>> triangle_b = AcuteTriangle(3, 3, 3, 60) >>> print(isinstance(triangle_a, Triangle)) True >>> print(isinstance(triangle_a, AcuteTriangle)) False >>> print(isinstance(triangle_b, AcuteTriangle)) True >>> print(isinstance(triangle_b, Triangle)) True >>> print(issubclass(AcuteTriangle, Triangle)) True >>> print(issubclass(Triangle, AcuteTriangle)) False
因?yàn)轭?AcuteTriangle
是從類 Triangle
派生出來(lái)的,所以一個(gè)類 AcuteTriangle
對(duì)象當(dāng)然也是一個(gè)類 Triangle
對(duì)象,正如“一個(gè)銳角三角形也是一個(gè)三角形”。
1.3.2 多繼承
一個(gè)類可以繼承多個(gè)類的特性,這也稱為多繼承,例如:
class RightTriangle(Triangle): def area(self): return self.edge_1 * self.edge_2 * 0.5 def print_name(self): print('This is a right triangle!') class IsoscelesTriangle(Triangle): def print_name(self): print('This is an isosceles triangle!') class IsoscelesRightTriangle(RightTriangle, IsoscelesTriangle): pass
以上示例中,pass
語(yǔ)句不做任何事,其作用相當(dāng)于占位符,以等待后續(xù)補(bǔ)充代碼;也可以用于語(yǔ)法上需要語(yǔ)句而實(shí)際不需要做任何工作的地方。
2. 模塊
我們已經(jīng)知道,函數(shù)和類都是可以重復(fù)調(diào)用的代碼塊。在程序中使用位于不同文件的代碼塊的方法是:導(dǎo)入 (import
) 該對(duì)象所在的模塊 (mudule
)。
在之前的示例中,我們總是使用 shell
,或假設(shè)整個(gè)程序保存在一個(gè)文件中,這在程序比較小時(shí)可能沒(méi)有什么問(wèn)題。但程序變得越來(lái)越大時(shí),將程序的不同部分根據(jù)不同分類方法保存在不同文件中通常會(huì)更加方便。
2.1 導(dǎo)入模塊
Python 模塊允許我們方便地使用多個(gè)文件中的代碼來(lái)構(gòu)建程序。模塊就是一個(gè)包含 Python 定義和語(yǔ)句的 .py 文件。
例如我們創(chuàng)建一個(gè) hello_world.py 文件,就可以理解為創(chuàng)建了一個(gè)名為 hello_world 的模塊:
# hello_world.py def print_hello(): print('Hello World!') class Triangle: def __init__(self, edge_1, edge_2, edge_3): self.edge_1 = edge_1 self.edge_2 = edge_2 self.edge_3 = edge_3 def __str__(self): return str((self.edge_1, self.edge_2, self.edge_3)) def print_info(self): print('The three sides of a triangle are {}, {} and {}'.format(self.edge_1, self.edge_2, self.edge_3)) def perimeter(self): return self.edge_1 + self.edge_2 + self.edge_3
可將模塊視為擴(kuò)展,要導(dǎo)入模塊,需要使用關(guān)鍵字 import,導(dǎo)入模塊的一般格式如下:
import module_1[, module_2....] # 可以同時(shí)導(dǎo)入多個(gè)模塊
例如在 test.py 文件要導(dǎo)入 hello_world 模塊:
import hello_world
導(dǎo)入的模塊只要說(shuō)明模塊名即可,不需要也不能帶有文件擴(kuò)展名 .py。如果要使用模塊中的對(duì)象,如函數(shù)、類等,需要用使用句點(diǎn)運(yùn)算符 (.),即使用“模塊名.對(duì)象”進(jìn)行訪問(wèn)。例如,使用 hello_worl.Triangle 訪問(wèn)模塊 hello_world 中的類 Triangle:
# test_1.py import hello_world hello_world.print_hello() tri_a = hello_world.Triangle(3, 4, 5) print(tri_a)
程序輸出如下所示:
Hello World!
(3, 4, 5)
需要注意的是,導(dǎo)入的模塊要位于相同的目錄層次下,否則需要添加目錄結(jié)構(gòu),例如,如果 hello_world 位于子目錄 module 下,則需要使用如下方式:
# test_2.py import module.hello_world module.test.print_hello()
程序輸出如下所示:
Hello World!
2.2 導(dǎo)入Python標(biāo)準(zhǔn)模塊
Python 提供了許多標(biāo)準(zhǔn)模塊,這些模塊文件位于 Python 安裝目錄的 lib 文件夾中。可以像導(dǎo)入自己編寫(xiě)的模塊一樣導(dǎo)入標(biāo)準(zhǔn)模塊,例如導(dǎo)入 math 模塊,使用其中的對(duì)象:
# test_3.py import math print('sqrt(4) = ', math.sqrt(4)) print('sin(π/6) = ', math.sin(math.pi /6))
程序輸出如下所示:
sqrt(4) = 2.0
sin(π/6) = 0.49999999999999994
這里可能大家會(huì)有一個(gè)疑問(wèn),這里導(dǎo)入的模塊和當(dāng)前文件并不在同一目錄下,為什么不需要使用模塊路徑?這個(gè)問(wèn)題也可以轉(zhuǎn)換為——當(dāng)我們使用 import 語(yǔ)句的時(shí)候,Python 解釋器是怎樣找到對(duì)應(yīng)的文件的呢?
這就涉及到 Python 的搜索路徑,搜索路徑是由一系列目錄名組成的,Python 解釋器就依次從這些目錄中去尋找所引入的模塊。搜索路徑被存儲(chǔ)在 sys 模塊中的 path 變量中:
>>> import sys >>> sys.path ['', 'D:\\Program Files\\Python39\\python39.zip', 'D:\\Program Files\\Python39\\DLLs', 'D:\\Program Files\\Python39\\lib', 'D:\\Program Files\\Python39', 'D:\\Program Files\\Python39\\lib\\site-packages'
2.3 單獨(dú)導(dǎo)入模塊中所需對(duì)象
我們可能不想每次調(diào)用模塊中的對(duì)象時(shí)都指定模塊名,這時(shí),我們可以使用 from module import object,從模塊中單獨(dú)導(dǎo)入所需對(duì)象,同時(shí)使用這個(gè)單獨(dú)導(dǎo)入的對(duì)象時(shí)就不需要在前面添加“模塊名.”前綴了:
# test_4.py from math import pi, sin print('sqrt(4) = ', sqrt(4)) print('sin(π/6) = ', sin(math.pi /6))
2.4 導(dǎo)入模塊中的所有對(duì)象
可以通過(guò) from module import *導(dǎo)入模塊中的所有對(duì)象,同樣不再需要模塊名前綴:
# test_5.py from math import * print('sqrt(4) = ', sqrt(4)) print('sin(π/6) = ', sin(math.pi /6))
不同程序代碼中不可避免地可能會(huì)使用了同一個(gè)名字來(lái)命名不同對(duì)象,這時(shí)就會(huì)引起沖突,但如果這些名字屬于不同的模塊,就可以通過(guò)模塊名來(lái)區(qū)分它們,因此為了避免名字沖突,應(yīng)盡量避免使用 from module import object 或 from module import * 導(dǎo)入對(duì)象。
2.5 重命名導(dǎo)入模塊或?qū)ο?/h3>
另一種避免名字沖突的方法是重命名導(dǎo)入模塊或?qū)ο螅?/p>
# test_6.py import math as m from datetime import date as d print(d.today()) print('sqrt(4) = ', m.sqrt(4)) print('sin(π/6) = ', m.sin(math.pi /6))
程序輸出如下所示:
datetime.date(2021, 12, 3)
sqrt(4) = 2.0
sin(π/6) = 0.49999999999999994
可以看到附加的好處是可以使用簡(jiǎn)寫(xiě),減少編碼工作量。
2.6 導(dǎo)入第三方模塊
除了標(biāo)準(zhǔn)庫(kù)外,Python 也具有規(guī)模龐大的第三方庫(kù),覆蓋了信息技術(shù)幾乎所有領(lǐng)域,這也是 Python 的其中一個(gè)巨大優(yōu)勢(shì)。下面以常用可視化庫(kù) matplotlib 為例介紹第三方庫(kù)的使用。和標(biāo)準(zhǔn)庫(kù)不同,使用第三方庫(kù)首先要進(jìn)行安裝,在 shell 命令中使用 pip 命令可以快速安裝所需庫(kù):
pip install matplotlib
安裝完成后,使用第三方庫(kù)就和標(biāo)準(zhǔn)庫(kù)沒(méi)有任何差別了:
# cos_1.py import math from matplotlib import pyplot as plt scale = range(100) x = [(2 * math.pi * i) / len(scale) for i in scale] y = [math.cos(i) for i in x] plt.plot(x, y) plt.show()
以上就是深入了解Python的類與模塊化的詳細(xì)內(nèi)容,更多關(guān)于Python 類 模塊化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
PyQt5主窗口動(dòng)態(tài)加載Widget實(shí)例代碼
這篇文章主要介紹了PyQt5主窗口動(dòng)態(tài)加載Widget實(shí)例代碼,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02閉包在python中的應(yīng)用之translate和maketrans用法詳解
這篇文章主要介紹了閉包在python中的應(yīng)用之translate和maketrans用法,是比較實(shí)用的技巧,需要的朋友可以參考下2014-08-08python實(shí)現(xiàn)桌面托盤(pán)氣泡提示
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)桌面托盤(pán)氣泡提示,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07Python 獲取命令行參數(shù)內(nèi)容及參數(shù)個(gè)數(shù)的實(shí)例
今天小編就為大家分享一篇Python 獲取命令行參數(shù)內(nèi)容及參數(shù)個(gè)數(shù)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12Python json模塊與jsonpath模塊區(qū)別詳解
這篇文章主要介紹了Python json模塊與jsonpath模塊區(qū)別詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03django創(chuàng)建超級(jí)用戶時(shí)指定添加其它字段方式
這篇文章主要介紹了django創(chuàng)建超級(jí)用戶時(shí)指定添加其它字段方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05