函式引數詳解

城南孤城發表於2021-01-04

一,什麼是函式

如果在開發程式時 ,需要某塊程式碼塊多次執行。

為了提高編寫的效率以及更好去維護程式碼,需要把具有獨立功能的程式碼組織成一個小模組,這個就是函式

  1. 函式的格式

def 函式名字():
	執行程式碼

  1. 定義了函式之後,就相當於他有了一個具有某些功能的程式碼,想讓這些程式碼能去執行,我們就需要去呼叫他
  2. 函式被定義之後是不會自動的去執行,需要我們自己去呼叫它
  3. 如果需要執行函式體裡面的程式碼,我們就需要去手動呼叫函式
  4. 需要主義的是,我們每次呼叫函式都會讓他從頭開始,當這個函式中的程式碼執行完畢之後,就意味著呼叫結束了。
  5. 如果在函式執行的過程中,函式碰到了 return 那麼他也會結束函式
  • 接下來是示例程式碼
def sums():
    print('666')
#函式呼叫好了不會自動去執行 而是需要去呼叫
sums()

def tell_story():
    print('從前有座山')
    print('山上有座廟')
    print('廟裡有個老和尚')
    print('還有個小和尚')
    print('老和尚在給小和尚講故事')
    print('故事的內容是:')


age = int(input('請輸入孩子的年齡'))
if  0<=age<=3:
    for x in range(5):
        tell_story()
elif 3<age<=5:
    tell_story()


def tell_story():
    return '從前有座山'+'山上有座廟'+'廟裡有個老和尚'+'還有個小和尚'+'老和尚在給小和尚講故事'+'故事的內容是:'

print(tell_story())

二,函式的引數

  • 說完了函式,接下來就是函式的引數。

  • 為了讓一個函式更通用,即想讓它計算哪兩個數的和,就讓它計算哪兩個數的和,在定義函式的時候可以讓函式接收資料,就解決了這個問題,這就是 函式的引數

1)定義,呼叫帶有引數的函式

定義一個add2num(a, b)函式,來計算任意兩個數字之和:

def add2num(a, b):
    c = a+b
    print c

add2num(11, 22) # 呼叫帶有引數的函式時,需要在小括號中,傳遞資料
Copy

注意點:

  • 在定義函式的時候,小括號裡寫等待賦值的變數名
  • 在呼叫函式的時候,小括號裡寫真正要進行運算的資料
    #將實際引數返回到形式引數
def sums(num1,num2,num3):   #num1,num2,num3  統稱為形式引數
    """
    這個函式是用來求三個函式的和
    :param num1:    #第一個數字
    :param num2:    #第二個數字
    :param num3:    #第三個數字
    :return:        #三個數字的和
    """
    return num1+num2+num3   #  return 返回引數

print(sums(100,200,300))   #統稱為實際引數 
  • 這個地方的意思是,定義一個sums函式,並且定義了3個值

  • 所以在我們完成程式碼的時候需要將 sums中的3個值傳進去,不然程式將會出現報錯

  • 再來一個示例程式碼

    def tell_story(p1,p2):
        """
    
        :param p1:
        :param p2:
        :return:
        """
        print('從前有座山')
        print('山上有座廟')
        print('廟裡有個'+p1)
        print('還有個'+p2)
        print(p1+'再給'+p2+'講故事')
        print('故事的內容是')
    
    tell_story('老尼姑','小和尚')
    tell_story(p1='小和尚',p2='老尼姑')
    
  • 這裡在最後面將 P1 P2 給定了值,所以他會按照給定的順序來傳值 如果,沒有給定順序,那麼將會按著順序傳上去

接下來,做兩個小練習

練習1,設計一個函式,傳入的引數是一個列表,返回去掉列表中重複元素之後的列表。

提示,set集合可以去重

def remove_item(lists):     #定義一個引數
    """

    :param list2:
    :return:
    """
    return list(set(lists))   #返回函式
print(remove_item([1,2,3,1,1,3,5,6,8]))

練習2,設計一個函式,傳入的引數是一個列表,返回去掉列表中重複元素之後的列表,列表中的元素需要保持原來的順序。

def remove_itmel(lists):    #定義一個引數
    res=[]
    see = set()
    for li in lists:
        if li not in see:
            res.append(li)
            see.add(li)
    return res          #返回函式   如果返回的是res  將不會自動排序,如果返回的是see就會自動排序
print(remove_itmel([1,3,5,6,9,7,4,4,6,45,2,3]))
來幾個簡單的程式碼,好理解一下
def hengxian():
    """

    :return:
    """
    return ("-"*30)	#返回的東西是 (=*30)
print(hengxian())	#然後輸出



def huaxian(a):
    for x in range(0,a):
        print( '-'*10)
        return a

print(int(input('定義行數')))	





def fact(num):
    x = 1
    for res in range(1, num+1):
        x*= res
    return x
print(fact(6))

在函式中,有一個全域性變數 還有一個區域性變數

但是if for while這些語句都不存在全域性變數這一說

kangbazi = '123'

def tses():
    global kangbazi
    kangbazi= '654'
    print(kangbazi)

def test():
    print(kangbazi)

tses()  #宣告呼叫
test()

if for while   都不存在全域性變數這一說
if 4>3:
    m = 'test'
print(m)

for x in range(0,2):

三,函式的返回值

一、“返回值”介紹

現實生活中的場景:

我給兒子10塊錢,讓他給我買個冰淇淋。這個例子中,10塊錢是我給兒子的,就相當於呼叫函式時傳遞到引數,讓兒子買冰淇淋這個事情最終的目標,我需要讓他把冰淇淋帶回來,此時冰淇淋就是返回值

開發中的場景:

定義了一個函式,完成了獲取室內溫度,想一想是不是應該把這個結果給呼叫者,只有呼叫者擁有了這個返回值,才能夠根據當前的溫度做適當的調整

綜上所述:

  • 所謂“返回值”,就是程式中函式完成一件事情後,最後給呼叫者的結果
  • 使用返回值的前提需求就是函式呼叫者想要在函式外使用計算結果

二、帶有返回值的函式

想要在函式中把結果返回給呼叫者,需要在函式中使用return

如下示例:

def add2num(a, b):
    c = a+b
    return c  # return 後可以寫變數名
Copy

或者

def add2num(a, b):
    return a+b  # return 後可以寫計算表示式
Copy

三、儲存函式的返回值

在本小節剛開始的時候,說過的“買冰淇淋”的例子中,最後兒子給你冰淇淋時,你一定是從兒子手中接過來 對麼,程式也是如此,如果一個函式返回了一個資料,那麼想要用這個資料,那麼就需要儲存

儲存函式的返回值示例如下:

#定義函式
def add2num(a, b):
    return a+b

#呼叫函式,順便儲存函式的返回值
result = add2num(100,98)

#因為result已經儲存了add2num的返回值,所以接下來就可以使用了
print(result)
Copy

結果:

198
小例子
def sums(a,b):
    """
    這是一個求和函式
    :param a:
    :param b:
    :return: 返回兩個數的和
    """
    c = a+b
    return c

res = sums(b=10,a=100)
x = print(res ** 4) # print內建函式  不能報錯它的結果
print(x) #None

y = input('請輸入一個值')
print(y)

函式的文件註釋

在函式寫完了函式名和形式引數之後,可以在下面說明這個地方傳的值是什麼,使用的引數是那個

然後是重頭戲

四,函式的呼叫

我直接用程式碼加註釋來解釋

ef sums(a,b):
    return a+b


def test(a,b,c):
    return a+sums(b,c)


res = test(10,20,30)
print(res)

#練習1:設計一個函式,傳入的引數是一個列表,返回去掉列表中重複元素之後的列表。
def remove_item(lists):
    """
    給列表去重
    :param list: 引數是一個列表
    :return: 返回一個列表 去重以後的
    """
    return list(set(lists))

# print(remove_item([1,1,2,1,3,4,2,3]))

#練習2:設計一個函式,傳入的引數是一個列表,返回去掉列表中重複元素之後的列表,列表中的元素需要保持原來的順序。

def remove_item1(lists):
    res = []
    see = set()
    for li in lists:
        if li not in see:
            res.append(li)
            see.add(li)
    return res
print(remove_item1([8,1,4,2,1,3,4,2,3]))

函式的呼叫二

# 定義一個函式  求 [n,m)之間所有整數的和
# def add(n,m):
#     sums = 0
#     for x in range(n, m):
#         sums += x
#     return sums

# sums = 0
# for x in range(10,100):
#     sums+=x
# print(sums)

# print(add(10,100))

#求 n的階乘  5的階乘 1*2*3*4*5

def factorial(num):
    x = 1
    for res in range(1, num+1):
        x *= res
    return x
# print(factorial(5))

# x = 1
# for res in range(1,6):
#     x*=res
# print(x)

#求 n的 階乘的和  以5為例子    1!+2!+3!+4!+5!
# res = 0
# for x in range(1,6):
#     res+=factorial(x)
# print(res)
# test = 100 #全域性變數
# def factorial_sum(m):
#     haha = 666 #區域性變數
#     res = 100
#     for x in range(1,m+1):
#         res+=factorial(x)
#     return res
#
# # print(factorial_sum(5))
# print(test)
# # print(haha) #報錯  全域性下不能列印區域性的變數
  • 這樣就引出了一個新的東西,就是全域性變數和區域性變數

五,全域性變數 區域性變數

kangbazi = 'wh2003'  #所有的函式都可以用


def test1():
    kangbazi = 999 #區域性變數
    print(kangbazi) #如果自己的範圍內有kangbazi 就呼叫該範圍的  沒有 呼叫全域性的
    # print(haha)

def test2():
    print(kangbazi)
    # print(haha) #報錯


test1()
test2()
  • 如果一個變數,既能在一個函式中使用,也能在其他的函式中使用,這樣的變數就是全域性變數
  • 打個比方:有2個兄弟 各自都有手機,各自有自己的小祕密在手機裡,不讓另外一方使用(可以理解為區域性變數);但是家裡的電話是2個兄弟都可以隨便使用的(可以理解為全域性變數)

  • 總結:

    • 在函式外邊定義的變數叫做全域性變數
    • 全域性變數能夠在所有的函式中進行訪問

全域性變數和區域性變數名字相同問題

  • 當函式內出現區域性變數和全域性變數相同名字時,函式內部中的 變數名 = 資料 此時理解為定義了一個區域性變數,而不是修改全域性變數的值

修改全域性變數

總結:

  • 如果在函式中出現global 全域性變數的名字 那麼這個函式中即使出現和全域性變數名相同的變數名 = 資料 也理解為對全域性變數進行修改,而不是定義區域性變數
  • 如果在一個函式中需要對多個全域性變數進行修改,那麼可以一次性全部宣告,也可以分開宣告
# 可以使用一次global對多個全域性變數進行宣告
global a, b
# 還可以用多次global宣告都是可以的
# global a
# global b

檢視所有的全域性變數和區域性變數

Python提供了兩個內建函式globals()和locals()可以用來檢視所有的全域性變數和區域性變數。

def test():
    a = 100
    b = 40
    print(locals())  # {'a': 100, 'b': 40}

test()

x = 'good'
y = True
print(globals())  # {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x101710630>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/jiangwei/Desktop/Test/test.py', '__cached__': None, 'test': <function test at 0x101695268>, 'x': 'good', 'y': True}

修改多個全域性變數

#
# kangbazi = 'whpy2003'
#
#
# def test():
#     # kangbazi = 'haha' #這個時候並不是說重新給全域性變數kangbazi 重新賦值進行修改
#     # #而是宣告瞭一個區域性變數  只能在test裡邊使用的
#     # print(kangbazi) # haha
#     global kangbazi #宣告kangbazi 是全域性變數
#     kangbazi = 'wuhanpython2003'
#     print(kangbazi)
#
# def test1():
#     print(kangbazi)
# test()
# test1()

# words = '你好'
#
# def test():
#     x = 'hello'
#     global words
#     words = '你好,滅霸'
#     print('locals={},globals={}'.format(locals(),globals()))
#
# test()
# #locals={'x': 'hello'},globals={'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001BA37C2E788>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/www/whpy03/day9/08修改全域性變數.py', '__cached__': None, 'words': '你好', 'test': <function test at 0x000001BA37CA2A68>}
#
# print('函式的外部words={}'.format(words))
# # print('函式的內部x={}'.format(x)) #報錯
#
# #locals() 內建函式  顯示 當前區域內所有的區域性變數
# #globals() 內建函式  顯示當前 .py檔案 全域性變數


# if 4>3:
#     m = 'test'
#
# print(m)

# for x in  range(5):
#     haha = 'test'
#     print(x)
#
# print(haha)

# if for while 裡邊不存在什麼全域性變數 區域性變數這一說

# i = 0
# while i<5:
#     test = 'hahahahahaah'
#     print(i)
#     i+=1
# print(test)

def kangbazi(str1,str2):
    """

    :param str1:
    :param str2:
    :return:
    """

要在函式內部修改全域性變數必須使用global

六,多個返回值

一、多個return?

def create_nums():
    print("---1---")
    return 1  # 函式中下面的程式碼不會被執行,因為return除了能夠將資料返回之外,還有一個隱藏的功能:結束函式
    print("---2---")
    return 2
    print("---3---")

總結1:

  • 一個函式中可以有多個return語句,但是隻要有一個return語句被執行到,那麼這個函式就會結束了,因此後面的return沒有什麼用處

  • 如果程式設計為如下,是可以的因為不同的場景下執行不同的return

      def create_nums(num):
          print("---1---")
          if num == 100:
              print("---2---")
              return num+1  # 函式中下面的程式碼不會被執行,因為return除了能夠將資料返回之外,還有一個隱藏的功能:結束函式
          else:
              print("---3---")
              return num+2
          print("---4---")
    
      result1 = create_nums(100)
      print(result1)  # 列印101
      result2 = create_nums(200)
      print(result2)  # 列印202
    
    

二、一個函式返回多個資料的方式

def divid(a, b):
    shang = a//b
    yushu = a%b 
    return shang, yushu  #預設是元組

result = divid(5, 2)
print(result)  # 輸出(2, 1)
Copy
def calculate(num1,num2):
    """

    :param num1:
    :param num2:
    :return:
    """
    x = num1 + num2
    y = num1 - num2
    z = num1 * num2
    h = num1 / num2
    return x,y,z,h # 本質返回的是一個元組
    # return {'x':x,'y':y,'z':z,'h':h}
    # return [x,y,z,h]
# print(calculate(1,2)) #(3, -1, 2, 0.5)
# res = calculate(1,2)
# print(res[0])

he,cha,ji,shang = calculate(1,2)
print(he,cha,ji,shang)

總結2:

  • return後面可以是元組,列表、字典等,只要是能夠儲存多個資料的型別,就可以一次性返回多個資料。

          def function():
              # return [1, 2, 3]
              # return (1, 2, 3)
              return {"num1": 1, "num2": 2, "num3": 3}
    Copy
    
  • 如果return後面有多個資料,那麼預設是元組。

對返回的資料直接拆包

def get_my_info():
    high = 178
    weight = 100
    age = 18
    return high, weight, age  # 函式返回三個資料,會自動打包為元組

# result = get_my_info()  # result 接收到一個元組
# print(result)

my_high, my_weight, my_age = get_my_info()  # 直接把元組拆分為三個變數來使用,更加方便
print(my_high)
print(my_weight)
print(my_age)
Copy

總結:

  • 拆包時要注意,需要拆的資料的個數要與變數的個數相同,否則程式會異常
  • 除了對元組拆包之外,還可以對列表、字典等拆包

七,函式引數詳解

一、預設引數

呼叫函式時,預設引數的值如果沒有傳入,則取預設值。

下例會列印預設的age,如果age沒有被傳入:

def printinfo(name, age=35):
   # 列印任何傳入的字串
   print("name: %s" % name)
   print("age %d" % age)

# 呼叫printinfo函式
printinfo(name="miki")  # 在函式執行過程中 age取預設值35
printinfo(age=9 ,name="miki")
Copy

以上例項輸出結果:

name: miki
age: 35
name: miki
age: 9
Copy

總結:

  • 在形參中預設有值的引數,稱之為預設引數

  • 注意:帶有預設值的引數一定要位於引數列表的最後面

      >>> def printinfo(name, age=35, sex):
      ...     print name
      ...
        File "<stdin>", line 1
      SyntaxError: non-default argument follows default argument
    Copy
    

二、不定長引數

有時可能需要一個函式能處理比當初宣告時更多的引數, 這些引數叫做不定長引數,宣告時不會命名。

基本語法如下:

def functionname([formal_args,] *args, **kwargs):
   """函式_文件字串"""
   function_suite
   return [expression]
Copy

注意:

  • 加了星號(*)的變數args會存放所有未命名的變數引數,args為元組
  • 而加**的變數kwargs會存放命名引數,即形如key=value的引數, kwargs為字典.
def test(a, b, *args, **kwargs):
      "函式在宣告時,需要兩個引數"
    print('a={},b={},args={},kwargs={}'.format(a,b,args,kwargs))

test(2, 3, '你好', 'hi', 'how do you do', name="zhangsan", age=18)
# a=2,b=3,args=('你好', 'hi', 'how do you do'),kwargs={'name': 'zhangsan', 'age': 18}


b = ('hi', '大家好', '今天天氣真好')
d = {'name': "zhangsan", "age": 19}

# 注意,在傳入引數時的星號問題。
test(10, 20, *b, **d) 
# a=10,b=20,args=('hi', '大家好', '今天天氣真好'),kwargs={'name': 'zhangsan', 'age': 19}


# 如果在傳值時,不使用星號,會把後面的引數當做 args
test(10,20,b,d)
# a=10,b=20,args=(('hi', '大家好', '今天天氣真好'), {'name': 'zhangsan', 'age': 19}),kwargs={}
Copy

三、預設引數在*args後面

def sum_nums_3(a, *args, b=22, c=33, **kwargs):
    print(a)
    print(b)
    print(c)
    print(args)
    print(kwargs)

sum_nums_3(100, 200, 300, 400, 500, 600, 700, b=1, c=2, mm=800, nn=900)
Copy

說明:

  • 如果很多個值都是不定長引數,那麼這種情況下,可以將預設引數放到 *args的後面, 但如果有**kwargs的話,**kwargs必須是最後的

相關文章