python3函數詳總結(語言儘量簡潔)

之前學函數總覺都不繫統,這次整理結合了太白金星的博客,但是是經過自己理解,精簡語言之後的內容。

函數:

def f_name(p1, p2, *args, p3=None, p4, **kwargs):
	
	...##此處是函數體
	
	return 
	'''
	函數到return結束
		1、return後面無值,則函數執行到這裏結束。
		2、return後面一個值,則返回這個值,函數結束。
		3、return後面你有多個返回值,則整體以一個元組的形式返回,可以在調用處使用結構接收返回值,函數結束。
	'''

調用處:

1、位置參數

f_name(p1, p2, p3)
'''
按照參數的先後順序傳遞參數
'''

2、關鍵字參數

f_name(p3 = v1, p1 = v2, p2 = v3)
'''
按照參數的名字傳參,不用考慮順序(v1、v2和v3是參數值)
'''

3、兩者結合使用:

f_name(p1, p3 = v3, p2 = v2)
'''
結合使用時,必須位置參數在前,關鍵字參數在後。
'''

實例:
def func(p1, p2, *args, p3=3, p4, **kwargs):
	
	print(p1, p2)
	print(args)
	print(p3, p4)
	print(kwargs)
	
	return 
	
func(1, 2, 3, 4, 5, p3=6, p4=7, a=1, b=2, c=3)
	
	
輸出:
	1 2
	(3, 4, 5)
	6 7
	{'a': 1, 'b': 2, 'c': 3}
	

函數定義處參數(形參):

1、位置參數:
形如:p1, p2。只接收一個量的參數,比如一個整數,一個小數,一個字符串,一個列表,一個元組。。。

def f_name(p1, p2):
	...
	
	return 

2、默認值參數:
形如p3=3,即在定義時就給變量一個默認值,這個值在實參處若給出則默認值被覆蓋,不給出則使用默認值

def f_name(p=3):
		...
		return
	1)f_name() #這樣調用時p的值默認爲3
	2)f_name(1) 或者 f_name(p=1) #這樣調用時p的值爲1

3、動態參數一,動態接收位置參數args:
形如
args,即在定義時加上號的參數,約定俗成一般使用args做參數名,即args,可以接受很多調用處的位置參數,並且將他們打包成元組(這裏是因爲*的“魔力”),傳給args,且這種參數只能定義一個

def f_name(*args):
		print(args)
		return 
	f_name(1, 2, 3, 4)
	
	輸出:
		(1,2,3,4)

4、動態參數二,動態接收關鍵字參數:
形如kwargs,即在定義時加上號的參數,約定俗成的一般使用kwargs做參數名,即**kwargs,可以接收很多調用處的關鍵字參數,並且把他們打包成字典,傳給kwargs,且這種參數只能定義一個

def f_name(**kwargs):
		print(kwargs)
		return 
	f_name(a=1, b=2)
	
	輸出:
		{'a': 1, 'b': 2}

5、python3新增參數類型,僅限關鍵字參數(不常用):
形如p4,定義在動態接受位置參數之後,動態接收關鍵字參數(若有的話)之前,和默認值參數沒有位置約束。接收且必須以關鍵字形式接受一個實參

def f_name(*args, f3=3, f4):
		print(args)
		print(p3, p4)
		
		return 
	或者:
	def f_name(*args, f4, f3=3):
		print(args)
		print(p3, p4)
		
		return
	
	f_name(1, 2, 3, p3=4, p4=5)
	
	輸出:
		(1, 2, 3)
		4 5

參數的順序:

位置參數,動態接收位置參數args, 默認值參數, 【僅限關鍵字參數】, 動態接收關鍵字參數。
討論:
首先位置參數肯定放在第一位的
然後動態接收位置參數
args和默認值參數誰在前呢? 肯定是args,假設默認值參數在前,如果使用位置傳參數的話,本來想傳給args的第一個參數會把默認值參數覆蓋掉他的默認值。
之後是默認值參數和動態關鍵字參數誰在前呢?當然是默認值參數,假設**kwargs在前,則所有的關鍵字參數都會傳給它,而默認值參數就永遠該變不了默認值了。
最後僅限關鍵字參數是一定在
args和**kwargs中間的,它和默認值參數的順序不受約束

*號的“魔力”:

*號的聚合和打散作用:
*號的聚合作用

剛剛我們說到的形參使用時,即args,會把傳過來的位置參數打包成元組,傳給args,這是一種聚合
還有**kwargs,會把傳過來的關鍵字參數打包成字典傳給kwargs

實例,聚合作用:
1)
def f_name(*args):
	print(args)
	return 
f_name(1, 2, 3, 4)

輸出:
	(1,2,3,4)

2)
def f_name(**kwargs):
	print(kwargs)
	return 
f_name(a=1, b=2)

輸出:
	{'a': 1, 'b': 2}

*號的打散作用:

另一種用法就是如果我們兩個列表list1和list2,想把他們的元素傳給*args怎麼辦到呢?
可以使用下面這種辦法:

	def f1(*args):
		print(args)
		return


	l1 = [1, 2, 3]
	s1 = '456'
	f1(*l1, *s1)##對列表、字符串、元組等迭代類型都可以
	
輸出:
	(1, 2, 3, '4', '5', '6')

另外一種情況,就是我們有兩個字典d1和d2,想把他們的元素傳給**kwargs怎麼辦到呢?
辦法類似:

def f2(**kwargs):
	print(kwargs)
	return

d1 = {
		'a' : 1,
		'b' : 2
	}
	d2 = {
		'3' : 3,
		'4' : 4
	}
f2(**d1, **d2)

輸出:

·{'a': 1, 'b': 2, '3': 3, '4': 4}

這是在函數傳參數時,那麼在函數外面呢?

函數外的聚合和打散:

**1、聚合(處理剩下的元素)**
我們這樣用過:
	a, b = (1, 2)
我們還可以這樣用:
  1)
	a, *b = [1, 2, 3, 4, 5]
	print(a, b)
  輸出:
	1 [2, 3, 4, 5]
  2)
	*a, b = [1, 2, 3, 4, 5]
	print(a, b)
  輸出:
	[1, 2, 3, 4] 5
	
**2、打散:**
	list1 = [1, 2, 3, 4, 5]
	print(*list1)
輸出:
	1 2 3 4 5
#### 總結:即*可以用來將剩下的元素聚合到一起,也可以將一個迭代對象打散。非常靈活。

名稱空間:

python在運行開始時會在內存中開闢一段空間,程序運行時遇到一個變量時就會把變量和值之間的關係記錄下來;遇到函數定義時,只把函數名記錄下來,不管函數內部的變量和邏輯。 只有當遇到函數調用的時候,python解釋器會再開闢一塊內存空間,用來存儲函數的變量,且這些變量只能在函數內部使用,隨着函數執行完畢,這塊內存也會被清空。

全局命名空間:

我們稱存儲變量和值關係的空間爲命名空間,程序開始時的命名空間爲全局命名空間。

局部命名空間:

在函數運行時臨時開闢的空間叫做局部命名空間,也叫臨時名稱空間

內置名稱空間:

在python執行時有一些我們沒有定義,卻拿來即用的變量和函數,如input,print,list,str等,這些存放在內置命名空間中。

加載順序:

首先在程序運行開始,內置名稱空間內的東西是拿來即用的,肯定首先加載進來,然後遇到變量聲明,函數定義,需要創建全局命名空間,之後每次遇到函數調用,都會爲每個函數創建臨時命名空間。所以加載順序應該是:
內置命名空間 -->> 全局命名空間 -->> 臨時命名空間1 -->>臨時命名空間2 …

取值順序:

取值順序採取就近原則,從最近的命名空間一步步到最外面的命名空間,所以順序爲:
臨時命名空間 -->> 全局命名空間 -->> 內置命名空間。

作用域:

作用域就是作用範圍,分爲全局作用域和局部作用域
全局作用域:全局命名空間+內置命名空間
局部作用域:局部命名空間

內置函數:

globals(): # 以字典的形式返回全局作用域所有的變量對應關係。

locals():  #以字典的形式返回當前作用域的變量的對應關係。

這裏一個是全局作用域,一個是當前作用域,一定要分清楚,接下來,我們用代碼驗證:
# 在全局作用域下打印,則他們獲取的都是全局作用域的所有的內容。

		a = 2
		b = 3
		print(globals())
		print(locals())
		'''
		{'__name__': '__main__', '__doc__': None, '__package__': None,
		'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001806E50C0B8>, 
		'__spec__': None, '__annotations__': {},
		'__builtins__': <module 'builtins' (built-in)>, 
		'__file__': 'D:/lnh.python/py project/teaching_show/day09~day15/function.py',
		'__cached__': None, 'a': 2, 'b': 3}
		'''

		# 在局部作用域中打印。
		a = 2
		b = 3
		def foo():
			c = 3
			print(globals()) # 和上面一樣,還是全局作用域的內容
			print(locals()) # {'c': 3}
		foo()

改變變量的作用域:

#先看一個現象:
	a = 1
	def func():
		print(a)
	func()
	a = 1
	def func():
		a += 1 # 報錯
	func()

也就是說全局變量在局部作用域不能做修改,只能讀。

一、python提供了一個關鍵字可以實現在局部作用域對全局變量做修改:global

#1、global的第一個功能,使全局變量可以在局部作用域修改:
	count = 1
	def search():
		global count
		count = 2
	search()
	print(count)
#2、global的第二個功能是,聲明一個全局變量:
	def func():
		global a
		a = 3
	func()
	print(a)

global的功能:

1、聲明一個全局變量
2、在局部作用域修改全局變量,需要用global

二、python3新加的功能nonlocal(使用較少),功能和global類似,不過只對父級(且父級不能爲全局作用域)作用域有效:

#例如:
		def add_b():
			##nonlocal b ##報錯
			b = 42
			def do_global():
				b = 10
				print(b)
				def dd_nonlocal():
					nonlocal b
					b = b + 20
					print(b)
				dd_nonlocal()
				print(b)
			do_global()
			print(b)
		add_b()
#輸出:
	10
	30
	30
	42

nonlocal功能:

1、不能更改全局變量
2、在局部作用域對父級作用域(或者更外層非全局作用域)的變量做修改,並且引用的哪層,從那層的及以下子層的變量全部發生改變。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章