Python基础第六天——函数的使用、函数的参数、函数的返回值、函数的嵌套、命名空间、作用域、函数对象...
一、拾遺
1、通常情況下無參函數只是進行操作,所以不需要返回值;有參數函數則需要返回值。
2、練習:
判斷用戶輸入一串字符,如果這串字符的長度小于5則重新輸入,如果大于5則退出循環。
while True:usr_input = input('Please input a string of characters:')res = len(usr_input) # 將len()函數的返回值存儲起來if res > 5:break?
?
?
?
二、函數的使用原則
1、函數與變量
(1)變量與函數的相似之處
函數的定義與變量的定義是相似的
變量名與函數名都是指向一塊內存地址
例:
變量:
x = 1?? # x是名字,1是值,表示變量名x指向了一個變量值 1
?
函數:
def func???? ? # func是名字,函數體print('ok')則是值,表示定義了一個名字叫func的函數,函數名則指向了函數體print('ok')。
print('ok')
?
變量和函數都是必須先定義后使用。
變量如果未定義就引用則相當于引用一個不存在的變量名,會提示變量名未定義
函數如果未事先定義函數而直接引用函數就相當于引用一個不存在的變量。會提示函數名未定義
?
(2)函數與變量的不同之處
變量名不需要加括號就能調用。
函數的調用必須要加上括號才能運行,因為函數里封裝了值,實際上是一段一段的代碼。所以要加上括號才能執行。
?
?
2、函數的常見錯誤
例1:函數事先未定義
解決方法:
在func()函數上面定義一個bar函數:
?
例2:以下函數執行時,很多人認為會報錯。其實并不會報錯。
print('from func')
bar()
def bar():
print('from bar')
func()
原因:
一定要熟練掌握函數的特性:先定義后調用!
func函數在定義時,函數體中的bar()并未執行,并且當調用func函數時也不會報錯,是因為在定義 bar函數時,函數名bar已經存在內存中了,所以,此時對func函數體中的bar調用,則會找到bar函數,并且調用bar函數里的函數體。
?
流程圖如下:
?
?
3、函數的定義階段與調用階段:
定義階段:只檢測語法,不執行代碼。
如果沒有語法錯誤,代碼就不會執行。如果有語法錯誤則會報錯
例:
?
?
?
三、函數的返回值:
python的函數可以有返回值也可以沒有返回值,看具體需求
1、語法:
def? 函數名(參數...):
函數體
return? 要返回的值
通常情況下,有參函數需要返回值,因為有參函數調用時要通過外部傳入進來值進行計算,最終要得到一個計算的結果,就要用到返回值的功能。
?
2、返回值的幾種形式
(1)沒有return默認返回:None
例:
?
(2)有return時可以返回一個或多個任意類型的值。當返回多個值時(用逗號隔開),得到元組的形式。
?例1:返回一個值
?
?
例2:返回多個值
?
?
(3)當函數中有多個return時,只能返回第一個return的值且函數終止運行
例:
?
四、位置參數與關鍵字參數
Python是一門弱類型的語言,它定義一個變量可以傳任意類型的值。
1、形參與實參
定義:形參只是形式存在,不是真的;實參是真實存在的,有值的。
例:
形參和實參的關系:
形參是變量名,實參是值,它們的關系是值一定要綁定給一個變量名才能夠存儲,所以形參在定義階段不會占用內存空間,只有在函數調用的時候才會綁定值,這層綁定關系只在調用時生效。當函數執行完后,這層綁定關系則會失效。
例:
?
2、位置參數
定義:按位置以逗號分隔從左至右的順序依次定義的參數叫做位置參數
(1)位置形參
特點:必須被傳值,不能多傳也不能少傳,否則報錯。
例:
?
?
(2)位置實參
特點:位置實參必須與位形參一 一對應
?
3、關鍵字參數
關鍵字參數指的是實參——關鍵字實參
特點:實參在定義時按照"key = value" (字典)的形式定義,不用像位置實參一樣一 一對應的傳值。指名道姓地傳值
例:
?
關鍵字實參與位置實參混用時要注意的問題:
問題一:
位置實參一定要在關鍵字實參的前面,否則報錯!
例:
問題二:
關鍵字實參與位置實參混用時,一個形參不能被重復傳值。
例1:
例2:
?
?
五、可變長參數
1、默認參數
默認參數指的是形參:在定義階段就已經為形參賦值。定義階段有值時,調用階段可以不用傳值
例1:
?
例2:
2、默認參數要注意的問題
在函數定義時:
(1)默認參數一定要在位置形參后面。
(2)默認參數通常要定義成不可變類型
(3)默認參數只在定義階段被賦值一次
?
通常情況下,默認參數用于很少改變值的情況下,而位置形參則用于經常要改變值的情況下:
例1:
進入公司應聘時,搞IT這塊的一般都是男的比較多,所以填寫時的性別可以默認為男性,這里就要用到默認參數:
?
例2:
?
3、可變長參數??????????? (重點)
定義:可變長參數指的是實參的個數不固定,所以形參必須要有一個規則來處理從實參傳過來的值。
(1)按位置定義的可變長度的實參:
符號: *
作用:接收按位置定義的實參,再賦值給一個變量保存下來,通常用變量名args表示: ?*args
例1:
?
例2 :
*(參數1,參數2,參數3...)??? ? ?等同于 ? ? ? ? 參數1,參數2,參數3...
?
(2)按關鍵字定義的可變長度的實參:
符號: **
作用:接收按關鍵字定義的實參,再賦值給一個變量保存下來,通常用變量名kwargs表示:? **kwargs
例:
?
?
例2:
**{‘key1’:value1,’key2‘:value2,‘key3’:value3...} 等同于 ? ? key1=value1,key2=value2,key3=value3...
?
(3)*args和**kwagrs連用時的作用:
兩者在一起時表示可以接收任意形式、任意長的參數
例1:
例2:裝飾器的雛形
?
4、 命名關鍵字參數 ? ? ??(不常用)
(1)命名關鍵字參數的用法
定義:在形參中,“ * ” 后面的參數叫命名關鍵字參數,這些參數必須要被傳值,且要求實參必須以關鍵字的形式傳值
例:
需求:讓用戶輸入姓名和年齡,并取出用戶的姓名和年齡
用戶一般都是不按常規了出牌,他不會老老實實地按照我們的流程來傳值,有時候,他只傳姓名或只傳年齡,這里我們的程序就要按以下方式寫
?
?所以,根據以上問題,我們必須將以上程序進行更改:
?
(2)命名關鍵字參數的補充——*args
?在形參中,“ * ”也可以換作 “*args”,表示能接收實參傳過來的任意長度的位置參數。
?例1:
?
(3)命名關鍵字參數的補充——命名關鍵字參數的默認值
<1>作用:限制實參必須以關鍵字的形式傳值。
<2>命名關鍵字參數的默認值與默認參數的區別:
它們的功能相同,區別在于它們在形參中的位置不同
命名關鍵字參數的默認值: ? ?
例:def register(*args,name='xiaobai',age):??? #?? 本例中的形參name和age只是命名關鍵字參數。
......
默認參數:默認參數必須在位置參數的后面
例:def register(name,age,sex='male') #? 默認參數必須在位置位置形參的后面
......
例1:
?
例2:
以下例子中,形參中的 “ * ” 后面定義的sex參數必須要被傳值,而"**kwargs"則表示接收其它傳進來的關鍵字實參。
?
例3:
?
?
?
?
六、函數的嵌套
函數的嵌套分為兩種:
1、函數的嵌套調用
作用:減少重復的代碼。
例:
?
2、函數的嵌套定義
?函數的定義實際上與定義變量是一樣,例:
定義變量:x = 1? ? ? ?# 定義了一個變量名:x
----------------------------------------------------------------
函數的定義:
def? x():???????? # 定義了一個函數名:x
pass
print(x) ? ? ? ??# 打印這個函數名x,可以得到x的對象,所以函數的定義時,看到def就相當于定義一個變量名。
?
函數的嵌套定義
例1:只打印函數f1里的代碼
?
?例2:打印函數f1和函數f2里的代碼
?
?
例3:執行函數f1、函數f2和函數f3里的代碼
?
執行函數f1、函數f2和函數f3里的代碼的過程:
第一步:
?
第二步:
?
第三步:
?
最終結果:
?
?
七、三種名稱空間
名稱空間
定義:存放名字與值的綁定關系的地方,呈現的都是字典的形式
例:之前學過的定義一個變量,如 ”x = 1“,”1“是被存放到內存開辟的一塊內存空間里了,那“x”這個變量名以及和值 “1”的綁定關系則被存放到了名稱空間里了。這個名稱空間它也是在內存里開辟了一塊空間。
?
名稱空間分為三種:
1、內置名稱空間
定義:Python解釋器自帶的變量名存放的空間。
生效:Python解釋器啟動則會生成內置名稱空間。
失效:關閉python解釋器后則失效
如:print、len、max、min、sum等等,只要python解釋器一啟動,這些名字便能直接使用。
?
2、全局名稱空間
定義:文件級別的名字都會存放到全局名稱空間。(不是內置的也不是函數內部定義的名字都是在全局名稱空間里)
生效:執行python文件時則會生成全局名稱空間。
失效:文件執行完后則失效
?
什么是文件級別的名字?
答:通俗地說就是頂頭寫且沒有縮進的變量名
例:
?
?
3、局部名稱空間
定義:定義在函數內部的名字
生效:函數調用時生效
失效:函數調用結束后失效
?例:
?
4、三種名稱空間的關系
按加載順序排序:內置名稱空間——>全局名稱空間——>局部名稱空間
按取值順序排序:局部名稱空間——>全局名稱空間——>內置名稱空間
例:
max是內置函數的變量名,現將max變量名分別定義成內置、全局、局部,此時這三個名稱空間里處存一份變量名。然后進行取值操作,證明它們的排序順序
步驟一:
?步驟二:
?
步驟三:
通過以上例子最終證明三種空間的取值順序是局部名稱空間——>全局名稱空間——>內置名稱空間
?
補充1:全局的局部仍然是全局
例:
?
?
?
補充2:名稱空間與名稱空間之間是一種互相隔離的關系。
例:用以下例子證明查找順序
?
?
八、作用域
定義:生效范圍
1、全局作用域
定義:包含內置名稱空間和全局名稱空間的名字,屬于全局范圍
生效:在整個文件的任意位置都能被引用,全局有效
例:
?
2、局部作用域
定義:局部名稱空間屬于局部范圍。
生效:只在函數內部可以被引用,局部有效
?只能從內看到外,不能從外看到內
例:
?
?
3、總結:
名稱空間只是用來存放名字的地方,而查找名字則與范圍有關
找一個名字跟所在的位置有關,這個所在的位置就是一個范圍的概念,它優先從當前位置開始找:
局部作用域——>全局作用域
所以作用域才是我們找名字的概念
?
4、globals和locals
globals是查看全局名稱空間的作用域的名字
返回的是當前的全局作用域的名字,而全局作用域的名字又包含全局和內置的名稱空間的名字
?
locals是查看局部作用域的名字
局部作用域只包含局部名稱空間自己的名字
例:
?
?
globals既包含全局名稱空間名字又包含內置名稱空間的名字
(1)globals查看全局名稱空間里的名字
(2)globals查看內置名稱空間的名字
查看得到的結果:
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip'] View Code?
?查看全局的范圍內的globals和locals,得到一個結果:全局的局部仍然是全局
?
?
九、函數對象
1、函數對象
在Python中,函數是第一類對象。
第一類對象:函數可以被當作數據傳遞。(數據可以做的事,函數也可以做,如:被引用、被當作參數傳到一個函數里、可以被當作參數的返回值、可以被當作容器類型的一個元素等)
?
?
例:
(1)被引用
(2)被當作函數的參數
(3)被當作函數的返回值
(4)當作容器類型的元素
?
?
?
?
?
?例:
?
?
?
接上面的例子,給變量f加上括號,相當于直接調用f2函數,因為能把它返回到任何位置,所以f2函數的調用不再受層級限制了,此時打印的結果是2,如下圖所示:
?
?繼續上面的例子,將f2函數中的x=2注釋后,此時的打印x值的結果為1,而不是去找函數外面的x = 0,這是因為作用域關系在函數定義階段就已經固定了,與調用位置無關。函數的調用不受層級限制,但是在調用的時候仍然要回到原來的位置去找作用域關系。
?
?
?
?
小練習:???? (重點)★★★★★
寫一個文件的增刪改查功能
要求:
與用戶交互,用多分支判斷,根據用戶輸入的內容不同執行不同的功能,如果用戶輸入的命令為空則繼續輸入,如果輸入的是查詢功能則調用查詢的函數,如果是刪除功能則調用delect()函數,這四個功能 只需要用print打印效果實現即可。
?
步驟一:
先定義好一個框架,如下圖所示:
步驟二:
將以上框架的代碼進行進一步優化
因為elif語句太多,如不將以上代碼優化,倘若有100個功能,則需要寫100個elif語句,所以為了減少代碼冗余,則修改為如下圖所示:
這種用字典來存放函數的形式可以很方便地添加新的功能的函數。
?
步驟3:
要求:將步驟2的代碼進行更改,條件如下:
用戶在輸入查詢功能時,不單單只輸入字符串select,很可能要對某一個文件的某一行內容進行查詢。比如:用戶輸入select xiaobai a.txt??? 表示用戶要在a文件里查詢是否包含有“xiaobai”字符串的內容。(用戶輸入的內容可以按照程序員自己定義的語法來寫邏輯,比如:select a.txt xiaobai)
根據以上需求,用戶此時輸入的命令不再是一個單純的命令了,這時得用到字符串的切片命令:split(),本例以空格作為分隔符,用戶則必須按照以空格作為分隔符來輸入命令。(這個規則由程序員自己定義)
代碼如下:
?運行得到以下效果:
表示將用戶輸入的字符串以列表的形式被select函數接收了
?
?
?步驟4:
創建一個a.txt的文件,文件內容如下:
?要求:寫一個查詢的功能,查出包含字符“python”的內容,并打印出該包含“python”關鍵字所在的行。
?
?源代碼:
只實現查了的功能
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # @File: 增刪改查功能.py # Author: xiaobai # @Time: 2017/10/19 0:57def select(x): # 查 # 下面函數調用傳進來了一個參數:“user_input_l”,所以要定義一個形參來接收。本例用“x”# print('select func',x) # 注釋select函數的打印功能filename = x[-1] # select函數接收的實參是['select','python','a.txt']# 用戶操作的文件名:a.txt在列表中是最后一個元素,所以寫成:x[-1]pattern = x[1] # (變量名pattern的中文為模式) 這里表示用戶要查找的內容:python,在列表的位置是1。with open(filename,'r',encoding='utf-8') as f:# 以讀的方式打開a.txt文件for line in f: # 循環a.txt里的每一行內容if pattern in line: # 判斷“python” 字符串是否在這行里。print(line) # 如果是則打印該行。 def delete(): # 刪print('delete func') def change(): # 改print('change func') def add(): # 增print('add func')func_dic = {'select':select,'delete':delete,'change':change,'add':add }# 用戶交互 while 1:user_input = input('Please give orders: ').strip() # 去掉字符串兩邊的空格if not user_input: # 判斷用戶輸入是否輸入字符串continueuser_input_l = user_input.split()# print(user_input_l) # 用戶輸入:select python a.txt 得到列表——['select', 'python', 'a.txt']# 判斷用戶輸入的指令中的第一個元素是否在func_dic字典里if user_input_l[0] in func_dic:func_dic[user_input_l[0]](user_input_l)# 如果是,則取出這個元素并將用戶輸入的命令整體傳進去else:print('The entered instruction is invalid')?輸出結果:
打印出了a.txt文件中包含"python"字符串所在的行
Please give orders: select python a.txt hello python View Code?
?
2、閉包的概念:
定義:定義在函數內部的函數稱為內部函數,該內部函數包含對外部作用域,且不是對全局作用域名字的引用,那么該內部函數稱為閉包函數。
舉個通俗易懂的例子:快遞送的包裹,這個包裹就類似于閉包,我們只看到這個包裹,看不到包裹內的東西。
轉載于:https://www.cnblogs.com/xiaoxiaobai/p/7674702.html
總結
以上是生活随笔為你收集整理的Python基础第六天——函数的使用、函数的参数、函数的返回值、函数的嵌套、命名空间、作用域、函数对象...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu14.04LTS opens
- 下一篇: css Table布局:基于displa