python基礎(12):函數(二)

1. 函數參數

以前咱們說過了傳參,若是咱們須要給⼀個函數傳參,⽽參數⼜是不肯定的,或者我給⼀個函數傳不少參數,個人形參就要寫不少,很⿇煩,怎麼辦呢,咱們能夠考慮使⽤動態參數。
形參的第三種: 動態參數
動態參數分紅兩種:

1.1 動態接收位置參數

⾸先咱們先回顧⼀下位置參數,位置參數,按照位置進⾏傳參
def chi(quality_food, junk_food):
  print("我要吃", quality_food, junk_food)

chi(
"⼤⽶飯", "⼩⽶飯") # "⼤⽶飯"傳遞給quality_food "⼩⽶飯"傳遞給junk_food,按照位置傳
如今問題來了,我想吃任意的食物,數量是任意的,食物也是任意的,這時咱們就要⽤到動態參數了。
在參數位置編寫*表⽰接收任意內容
def chi(*food):
  print("我要吃", food)

chi(
"⼤⽶飯", "⼩⽶飯")
結果: 我要吃 (
'⼤⽶飯', '⼩⽶飯') # 多個參數傳遞進去. 收到的內容是元組tuple
動態接收參數的時候要注意: 動態參數必須在位置參數後⾯。
def chi(*food, a, b):
  print("我要吃", food, a, b)

chi(
"⼤⽶飯", "⼩⽶飯", "⻩⽠", "茄⼦")
這時程序運⾏會報錯,由於前⾯傳遞進去的全部位置參數都被*food接收了,a和b永遠接收
不到參數。
Traceback (most recent call last):
   File "/Users/sylar/PycharmProjects/oldboy/fun.py", line 95, in <module>
   chi("⼤⽶飯", "⼩⽶飯", "⻩⽠", "茄⼦")
TypeError: chi() missing 2 required keyword-only arguments: 'a' and 'b'
因此必須改寫成如下代碼:
def chi(*food, a, b):
  print("我要吃", food, a, b)

chi(
"⼤⽶飯", "⼩⽶飯", a="⻩⽠", b="茄⼦") # 必須⽤關鍵字參數來指定
這個時候a和b就有值了,可是這樣寫呢位置參數就不能⽤了。因此,咱們要先寫位置參數,
而後再⽤動態參數。
def chi(a, b, *food):
  print("我要吃", a, b, food)

chi(
"⼤⽶飯", "⼩⽶飯", "饅頭", "⾯條") # 前兩個參數⽤位置參數來接收, 後⾯的參數⽤動態參數接收
那默認值參數呢?
def chi(a, b, c='饅頭', *food):
  print(a, b, c, food)

chi(
"⾹蕉", "菠蘿") # ⾹蕉 菠蘿 饅頭 (). 默認值⽣效 chi("⾹蕉", "菠蘿", "葫蘆娃") # ⾹蕉 菠蘿 葫蘆娃 () 默認值不⽣效 chi("⾹蕉", "菠蘿", "葫蘆娃", "⼝罩") # ⾹蕉 菠蘿 葫蘆娃 ('⼝罩',) 默認值不⽣效
咱們發現默認值參數寫在動態參數前⾯,默認值只有⼀種狀況可能會⽣效。
def chi(a, b, *food, c="娃哈哈"):
  print(a, b, food, c)

chi(
"⾹蕉", "菠蘿") # ⾹蕉 菠蘿 () 娃哈哈 默認值⽣效 chi("⾹蕉", "菠蘿", "葫蘆娃") # ⾹蕉 菠蘿 ('葫蘆娃',) 娃哈哈 默認值⽣效 chi("⾹蕉", "菠蘿", "葫蘆娃", "⼝罩") # ⾹蕉 菠蘿 ('葫蘆娃', '⼝罩') 娃哈哈 默認值⽣效
這個時候咱們發現全部的默認值都⽣效了,這個時候若是不給出關鍵字傳參,那麼你的默
認值是永遠都⽣效的。
順序: 位置參數,動態參數*,默認值參數。

1.2 動態接收關鍵字參數

在python中能夠動態的位置參數,可是*這種狀況只能接收位置參數⽆法接收關鍵字參數,在python中使⽤**來接收動態關鍵字參數。
def func(**kwargs):
  print(kwargs)

func(a
=1, b=2, c=3) func(a=1, b=2)
結果: {
'a': 1, 'b': 2, 'c': 3} {'a': 1, 'b': 2}
這個時候接收的是⼀個dict
順序的問題, 在函數調⽤的時候,若是先給出關鍵字參數,則整個參數列表會報錯。
def func(a, b, c, d):
  print(a, b, c, d)


# 關鍵字參數必須在位置參數後⾯, 不然參數會混亂 func(1, 2, c=3, 4)
因此關鍵字參數必須在位置參數後⾯,因爲實參是這個順序,因此形參接收的時候也是這
個順序。也就是說位置參數必須在關鍵字參數前⾯,動態接收關鍵字參數也要在後⾯。
 
最終順序(*):
位置參數 > *args > 默認值參數 > **kwargs
這四種參數能夠任意的進⾏使⽤。
若是想接收全部的參數:
def func(*args, **kwargs):
   print(args, kwargs)

func(
"麻花藤","⻢暈",wtf="胡辣湯")
動態參數的另⼀種傳參⽅式:
def fun(*args):
  print(args)

lst
= [1, 4, 7] fun(lst[0], lst[1], lst[2])
fun(
*lst) # 能夠使⽤*把⼀個列表按順序打散 s = "⾂妾作不到" fun(*s) # 字符串也能夠打散, (可迭代對象)
在實參位置上給⼀個序列,列表,可迭代對象前⾯加個*表⽰把這個序列按順序打散。
在形參的位置上的* 表⽰把接收到的參數組合成⼀個元組。
若是是⼀個字典,那麼也能夠打散,不過須要⽤兩個*。
def fun(**kwargs):
  print(kwargs)

dic
= {'a':1, 'b':2} fun(**dic)
函數的註釋:
def chi(food, drink):
  """
  這⾥是函數的註釋, 先寫⼀下當前這個函數是⼲什麼的, ⽐如我這個函數就是⼀個吃
  :param :param food: 參數food是什麼意思
  :param :param drink: 參數drink是什麼意思
  :return :return: 返回的是什麼東東
   """
  print(food, drink)
  return "very good"

2. 命名空間

在python解釋器開始執⾏以後,就會在內存中開闢⼀個空間,每當遇到⼀個變量的時候,就把變量名和值之間的關係記錄下來,可是當遇到函數定義的時候,解釋器只是把函數名讀入內
存,表⽰這個函數存在了,⾄於函數內部的變量和邏輯,解釋器是不關⼼的。也就是說⼀開始的時候函數只是加載進來,僅此⽽已,只有當函數被調⽤和訪問的時候,解釋器纔會根據函數
內部聲明的變量來進⾏開闢變量的內部空間。隨着函數執⾏完畢,這些函數內部變量佔⽤的空間也會隨着函數執⾏完畢⽽被清空。
def fun():
   a = 10
  print(a)

fun()
print(a) # a不存在了已經..
咱們給存放名字和值的關係的空間起⼀個名字叫: 命名空間。咱們的變量在存儲的時候就是存儲在這片空間中的。
命名空間分類:
1. 全局命名空間--> 咱們直接在py⽂件中, 函數外聲明的變量都屬於全局命名空間
2. 局部命名空間--> 在函數中聲明的變量會放在局部命名空間
3. 內置命名空間--> 存放python解釋器爲咱們提供的名字, list, tuple, str, int這些都是內置命名空間
加載順序:
1. 內置命名空間
2. 全局命名空間
3. 局部命名空間(函數被執⾏的時候)
取值順序:
1. 局部命名空間
2. 全局命名空間
3. 內置命名空間
a = 10
def func():
   a = 20
   print(a)

func()
# 20
做⽤域: 做⽤域就是做⽤範圍,按照⽣效範圍來看分爲全局做⽤域和局部做⽤域。
全局做⽤域: 包含內置命名空間和全局命名空間。在整個⽂件的任何位置均可以使⽤(遵循從上到下逐⾏執⾏)。局部做⽤域: 在函數內部能夠使⽤。
做⽤域命名空間:
1. 全局做⽤域: 全局命名空間 + 內置命名空間
2. 局部做⽤域: 局部命名空間
咱們能夠經過globals()函數來查看全局做⽤域中的內容,也能夠經過locals()來查看局部做
⽤域中的變量和函數信息。
a = 10
def func():
   a = 40
  b = 20
  def abc():
    print("哈哈")
  print(a, b) # 這⾥使⽤的是局部做⽤域
  print(globals()) # 打印全局做⽤域中的內容
  print(locals()) # 打印局部做⽤域中的內容

func()

3. 函數的嵌套

1. 只要遇⻅了()就是函數的調⽤,若是沒有()就不是函數的調⽤
2. 函數的執⾏順序
def fun1():
  print(111)
def fun2():
  print(222)
   fun1()


fun2()
print(111)

# 函數的嵌套 def fun2():   print(222)   def fun3():     print(666)   print(444) fun3()   print(888)   print(33) fun2() print(555)

4. 關鍵字global和nonlocal

⾸先咱們寫這樣⼀個代碼,⾸先在全局聲明⼀個變量,而後再局部調⽤這個變量,並改變這
個變量的值。
a = 100
def func():
  global a # 加了個global表示再也不局部建立這個變量了. ⽽是直接使⽤全局的a
  a = 28
  print(a)

func()
print(a)
global表⽰,再也不使⽤局部做⽤域中的內容了,⽽改⽤全局做⽤域中的變量。
lst = ["麻花藤", "劉嘉玲", "詹姆斯"]
def func():
  lst.append("⻢云云") # 對於可變數據類型能夠直接進⾏訪問. 可是不能改地址. 說⽩了. 不能賦值
  print(lst)

func()
print(lst)
nonlocal 表⽰在局部做⽤域中,調⽤⽗級命名空間中的變量。
a = 10
def func1():
  a = 20
  def func2():
    nonlocal a
    a = 30
    print(a)
  func2()
  print(a)

func1()
結果: 加了nonlocal
30 30 不加nonlocal 30 20
再看,若是嵌套了不少層,會是⼀種什麼效果:
a = 1
def fun_1():
  a = 2
  def fun_2():
    nonlocal a
    a = 3
    def fun_3():
      a = 4
      print(a)
    print(a)
    fun_3()
    print(a)
  print(a)
  fun_2()
  print(a)

print(a) fun_1() print(a)
這樣的程序若是能分析明⽩,那麼做⽤域,global、nonlocal就沒問題了。
相關文章
相關標籤/搜索