Python基础知识(第七天)
90.嵌套函數_內部函數_數據隱藏
嵌套函數
在函數內部定義的函數!
?一般在什么情況下使用嵌套函數?
1.封裝 - 數據隱藏
? ? ? ?外部無法訪問“嵌套函數”。
2.貫徹?DRY(Don’t Repeat Yourself)原則
? ? ? ?嵌套函數,可以讓我們在函數內部避免重復代碼。
3.閉包
? ? ? ?后面會詳細講解。
91.nonlocal_global
nonlocal 關鍵字
nonlocal 用來聲明外層的局部變量。
global 用來聲明全局變量。
a = 100 def outer():b = 10def inner():nonlocal b #聲明外部函數的局部變量print("inner b:",b)b = 20global a #聲明全局變量a = 1000inner() print("outer b:",b) outer() print("a:",a)inner b:? 10
outer b:? 20
a:? ? 1000
92.LEGB規則
Python 在查找“名稱”時,是按照LEGB 規則查找的:Local-->Enclosed-->Global-->Built
Local 指的就是函數或者類的方法內部
Enclosed 指的是嵌套函數(一個函數包裹另一個函數,閉包)
Global 指的是模塊中的全局變量
Built?in 指的是Python?為自己保留的特殊名稱。
如果某個name?映射在局部(local)命名空間中沒有找到,接下來就會在閉包作用域(enclosed)進行搜索,如果閉包作用域也沒有找到,Python?就會到全局(global)命名空間中進行查找,最后會在內建(built-in)命名空間搜索(如果一個名稱在所有命名空間中都沒有找到就會產生一個NameError)
93.面向對象和面向過程的區別_執行者思維_設計者思維
面向對象(Object oriented Programming,OOP)編程的思想主要是針對大型軟件設計而來的。面向對象編程使程序的擴展性更強、可讀性更好,使的編程可以像搭積木一樣簡單。
面向對象編程將數據和操作數據相關的方法封裝到對象中,組織代碼和數據的方式更加接近人的思維,從而大大提高了編程的效率。
Python完全采用了面向對象的思想,是真正面向對象的編程語言,完全支持面向對象的基本功能,例如:繼承、多態、封裝等。Python 中,一切皆對象。我們在前面學習的數據類型、函數等,都是對象。
面向對象和面向過程區別
面向過程(Procedure?Oriented)思維
面向過程編程更加關注的是“程序的邏輯流程”,是一種“執行者”思維,適合編寫小規模的程序。
面向過程適合簡單、不需要協作的事務。但是當我們思考比較復雜的問題,比如“如何造車?”,就會發現列出 1234?這樣的步驟,是不可能的。那是因為,造車太復雜,需要很多協作才能完成。此時面向對象思想就應運而生了。
面向對象(Object?Oriented)思維
面向對象(Object)思想更契合人的思維模式。我們首先思考的是“怎么設計這個事物?” ???比如思考造車,我們就會先思考“車怎么設計?”,而不是“怎么按步驟造車的問題”。這就是思維方式的轉變。
為了便于協作,我們找輪胎廠完成制造輪胎的步驟,發動機廠完成制造發動機的步驟,這樣,發現大家可以同時進行車的制造,最終進行組裝,大大提高了效率。但是,具體到輪胎廠的一個流水線操作,仍然是有步驟的,還是離不開面向過程思想!
我們千萬不要把面向過程和面向對象對立起來。他們是相輔相成的。面向對象離不開面向過程!
面向對象思考方式
遇到復雜問題,先從問題中找名詞(面向過程更多的是找動詞),然后確立這些名詞哪 ???些可以作為類,再根據問題需求確定的類的屬性和方法,確定類之間的關系。
94.對象的進化故事
對象的進化
隨著編程面臨的問題越來越復雜,編程語言本身也在進化,從主要處理簡單數據開始,隨著數據變多進化“數組”; 數據類型變復雜,進化出了“結構體”; 處理數據的方式和邏輯變復雜,進化出了“對象”。
1.簡單數據
像 30,40,50.4 等這些數字,可以看做是簡單數據。最初的計算機編程,都是像這樣的數字。
2.數組
將同類型的數據放到一起。比如:整數數組[20,30,40],浮點數數組[10.2, 11.3, 12.4], 字符串數組:[“aa”,”bb”,”cc”]
3.結構體
將不同類型的數據放到一起,是 C 語言中的數據結構。比如:
struct resume{
? ? int age;
? ? char?name[10];
? ? double?salary;
?};
4.對象
將不同類型的數據、方法(即函數)放到一起,就是對象。
95.類的定義_類和對象的關系
類的定義
我們把對象比作一個“餅干”,類就是制造這個餅干的“模具”。
我們通過類定義數據類型的屬性(數據)和方法(行為),也就是說,“類將行為和狀態打包在一起”。
??從一個類創建對象時,每個對象會共享這個類的行為(類中定義的方法),但會有自己的屬性值(不共享狀態)。更具體一點:“方法代碼是共享的,屬性數據不共享”。
Python 中,“一切皆對象”。類也稱為“類對象”,類的實例也稱為“實例對象”。
定義類的語法格式如下:
class 類名:
? ? ? 類體
要點如下:
1.類名必須符合“標識符”的規則;一般規定,首字母大寫,多個單詞使用“駝峰原則”。
2.類體中我們可以定義屬性和方法。
3.屬性用來描述數據,方法(即函數)用來描述這些數據相關的操作。?
class Student: # 類名一般首字母大寫,多個單詞采用駝峰原則def __init__(self, name, score): # 構造方法第一個參數必須為 selfself.score = scoreself.name = namedef say_score(self):print("{0}的分數是:{1}".format(self.name, self.score))s1 = Student("高崎", 18) s1.say_score()96.構造函數__init__
? init? 構造方法和? new? 方法
類是抽象的,也稱之為“對象的模板”。我們需要通過類這個模板,創建類的實例對象,然后才能使用類定義的功能。
我們前面說過一個 Python?對象包含三個部分:id(identity?識別碼)、type(對象類型)、value(對象的值)。
現在,我們可以更進一步的說,一個 Python 對象包含如下部分:
1.id(identity?識別碼)
2.type(對象類型)
3.value(對象的值) ?1)方法(method)? ? 2)屬性(attribute)
????init?()的要點如下:
1.名稱固定,必須為: init ()
2.第一個參數固定,必須為:self。self?指的就是剛剛創建好的實例對象。
3.構造函數通常用來初始化實例對象的實例屬性,如下代碼就是初始化實例屬性:name ???和 score。
def __init__(self, name, score): # 構造方法第一個參數必須為 selfself.score = scoreself.name = name?4.通過“類名(參數列表)”來調用構造函數。調用后,將創建好的對象返回給相應的變量。 ???比如:s1 = Student('張三', 80)
5.????init ()方法:初始化創建好的對象,初始化指的是:“給實例屬性賦值”
6.????new__()方法: 用于創建對象,但我們一般無需重定義該方法。
7.如果我們不定義?init 方法,系統會提供一個默認的??init??方法。如果我們定義了帶參的?init 方法,系統不創建默認的??init 方法。
97.實例屬性_內存分析
實例屬性
實例屬性是從屬于實例對象的屬性,也稱為“實例變量”。他的使用有如下幾個要點:
1.實例屬性一般在?init ()方法中通過如下代碼定義: self.實例屬性名 = 初始值
2.在本類的其他實例方法中,也是通過 self?進行訪問: self.實例屬性名
3.創建實例對象后,通過實例對象訪問:
obj01 =?類 名()? ? ? ? ? ? ? ? #創建對象,調用??init?()初始化屬性
obj01.實例屬性名?=?值? ? ? ? ? ? ? #可以給已有屬性賦值,也可以新加屬性
98.實例方法_內存分析方法調用過程_dir()_isinstance
實例方法
實例方法是從屬于實例對象的方法。實例方法的定義格式如下:
def 方法名(self?[,?形參列表]):
? ? ? ? ? 函數體
方法的調用格式如下:
? ? ? ? ? ?對象.方法名([實參列表])
要點:
1.定義實例方法時,第一個參數必須為 self。和前面一樣,self?指當前的實例對象。
2.調用實例方法時,不需要也不能給 self?傳參。self?由解釋器自動傳參
函數和方法的區別
1.都是用來完成一個功能的語句塊,本質一樣。
2.方法調用時,通過對象來調用。方法從屬于特定實例對象,普通函數沒有這個特點。
3.直觀上看方法定義時需要傳遞 self,函數不需要。?
?其他操作:
1.dir(obj)可以獲得對象的所有屬性、方法
2.obj.? ???dict__ 對象的屬性字典
3.pass?空語句
4.isinstance(對象,類型) 判斷“對象”是不是“指定類型”
99.類對象
類對象
我們在前面講的類定義格式中,“class類名:”。實際上,當解釋器執行?class?語句時, 就會創建一個類對象。
?我們可以看到實際上生成了一個變量名就是類名“Student”的對象。我們通過賦值給新變量 Stu2,也能實現相關的調用。說明,確實創建了“類對象”。
100.類屬性_內存分析創建類和對象的底層
類屬性
類屬性是從屬于“類對象”的屬性,也稱為“類變量”。由于,類屬性從屬于類對象,可以被所有實例對象共享。
類屬性的定義方式:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? class 類名:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 類變量名= 初始值
在類中或者類的外面,我們可以通過:“類名.類變量名”來讀寫。
class Student:company = "SXT" #類屬性count = 0 #類屬性def __init__(self,name,score):self.name = name #實例屬性self.score = scoreself.score = scoreStudent.count = Student.count+1def say_score(self): #實例方法print("我的公司是:",Student.company)print(self.name,'的分數是:',self.score)s1 = Student('張三',80) s1.say_score() print('一共創建{0}個 Student 對象'.format(Student.count))101.類方法_靜態方法_內存分析圖示
類方法
類方法是從屬于“類對象”的方法。類方法通過裝飾器@classmethod 來定義,格式如下:
@classmethod
def 類方法名(cls [,形參列
表])?: 函數體
要點如下:
1.@classmethod?必須位于方法上面一行
2.第一個 cls?必須有;cls?指的就是“類對象”本身;
3.調用類方法格式:“類名.類方法名(參數列表)”。 參數列表中,不需要也不能給 cls?傳值。
4.類方法中訪問實例屬性和實例方法會導致錯誤
5.子類繼承父類方法時,傳入 cls?是子類對象,而非父類對象
class Student:company = "SXT"@classmethoddef printCompany(cls): print(cls.company)Student.printCompany()靜態方法
Python 中允許定義與“類對象”無關的方法,稱為“靜態方法”。
“靜態方法”和在模塊中定義普通函數沒有區別,只不過“靜態方法”放到了“類的名字空間里面”,需要通過“類調用”。
靜態方法通過裝飾器@staticmethod 來定義,格式如下:
? ? ? ? ? ? ? ? ? ? ?@staticmethod
? ? ? ? ? ? ? ? ? ? ?def 靜態方法名([形參列表]) :
? ? ? ? ? ? ? ? ? ? ? ? ? 函數體
要點如下:
1.@staticmethod?必須位于方法上面一行
2.調用靜態方法格式:“類名.靜態方法名(參數列表)”。
3.靜態方法中訪問實例屬性和實例方法會導致錯誤
class Student:company = "SXT" #類屬性@staticmethoddef add(a, b): #靜態方法print("{0}+{1}={2}".format(a,b,(a+b)))return a+bStudent.add(20,30)靜態方法、類方法不能實例變量和實例方法。
102.__del__()析構方法和垃圾回收機制
????del????方法稱為“析構方法”,用于實現對象被銷毀時所需的操作。比如:釋放對象占用的資源,例如:打開的文件資源、網絡連接等。Python 實現自動的垃圾回收,當對象沒有被引用時(引用計數為0),由垃圾回收器調用????del????方法。
我們也可以通過 del?語句刪除對象,從而保證調用?del?方法。系統會自動提供?del?方法,一般不需要自定義析構方法。
class Person:def __del__ (self):print("銷毀對象:{0}".format(self)) p1 = Person() p2 = Person() del p2 print("程序結束")銷毀對象:<?main__.Person object at 0x02175610>
程序結束
銷毀對象:<?main__.Person object at 0x021755D0>
103.__call__()方法和可調用對象
定義了__call__方法的對象,稱為“可調用對象”,即該對象可以像函數一樣被調用。
class SalaryAccount:def __call__(self, salary):yearSalary = salary*12 daySalary = salary//30return dict(yearSalary=yearSalary,daySalary=daySalary)s = SalaryAccount() print(s(30000))總結
以上是生活随笔為你收集整理的Python基础知识(第七天)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python基础知识(第六天)
- 下一篇: Python基础知识(第八天)