Python入門-函數

< 返回索引頁html

<!-- /TOC -->數組

函數

在維基百科上函數式這樣描述的:數據結構

函數在數學中爲兩集合間的一種對應關係:輸入值集合中的每項元素皆能對應惟一一項輸出值集合中的元素。

此處的函數區別於咱們數學上的函數,在編程世界中,函數(Functions)是指可重複使用的程序片斷。它們容許你爲某個代碼塊賦予名字,容許你
經過這一特殊的名字在你的程序任何地方來運行代碼塊,並可重複任何次數。這就是所謂的調用函數。咱們已經使用過了許多內置的函數,例如 lenrange閉包

基本結構以下:app

def 函數名(參數列表):
    " 函數說明 "
    函數體

函數定義

在Python中,使用關鍵字def來定義一個函數。結構以下:函數

def hello(name):  
    " 返回字符串"
    return name
    
def hello2():
    pass

語法說明:學習

  • 函數的參數支持多種形式
  • 函數說明,可經過內部方法hello.__doc__ 獲取
  • 函數的返回值支持返回多個
  • 咱們可使用 pass 來定義個空函數

下面來展開一一講述。

返回值

函數中返回值,使用關鍵字return 來表示,返回值能夠是任意類型,當沒有return語句時函數返回None。函數返回值支持多個,返回多個時,使用逗號分隔。以下:

def say_hello(name):
    print(name)
    return 'Hello, %s' % name, name

函數的調用

函數的調用,上邊咱們已經使用了不少次了,函數名加上須要傳入的響應參數便可。這裏須要注意的是,在python中,一切結尾對象,固然函數也是對象。函數名也能夠做爲參數傳遞到函數中使用。

def say_hello(name):
    print('hello, %s' % name)

def wapper(fun):
    print('調用以前作一些事')
    fun('Dean')
    print('調用以後作一些事')

wapper(say_hello)
"""
調用以前作一些事
hello, Dean
調用以後作一些事
"""

函數的參數

在程序設計中函數參數有2個比較通用的概念,形參和實參,在各高級語言中都會有。形參,即形式上的參數,不佔用內存空間。實參,是實際真正的參數。

看下面這個實例:

def say_hello(name):  
    print('hello, %s' % name )
say_hello('Dean')

其中,函數參數name即爲函數的形參。咱們調用函數時,傳入的參數Dean即是實參。在Python編程時,這個概念並非那麼重要,此種瞭解便可。

順序參數

在Python 函數中,多個參數按照必定的順序依次傳入函數,其值依次對應賦給函數聲明時參數,這種參數叫順序參數

def say_hello(name, age):
    print('hello, %s' % name)
    print('you age: %s ' % age)

say_hello('Dean', 30)

如上,Dean與30 這2個參數按照由左到右依次賦值給形參nameage供函數內部使用。須要注意的是,順序參數中,形參和實參的個數須要一直,不然函數會報調用錯誤。

參數的默認值

在函數聲明時,能夠給參數設置默認值,以下:

def say_hello(name='Tim', age=20):
    print('hello, %s' % name)
    print('you age: %s ' % age)

say_hello('Dean', 30)
say_hello('Dean')

當函數參數設置默認值後,該參數在調用函數時,能夠省略,省略時則會使用默認值。有此能夠退出,參數沒有設置默認值,則是必傳的。

可變參數

有時候咱們在聲明函數時,無法肯定函數的參數個數,或者咱們自己就想設計一種動態的參數,這種設計是否能夠知足呢?Python的函數對這種狀況已作了考慮,提供了可變參數來知足這種需求。

def say_hello(*args):
    print(args)
    for name in args:
        print('hello, %s' % name)

say_hello('Dean','Tim')
('Dean', 'Tim')
hello, Dean
hello, Tim

可變參數使用*加一個形參來表示,其值爲一個元組類型,元組內的元素爲咱們傳入的實參。

關鍵字參數

在可變參數中,咱們傳入函數的參數只能按順序或着經過下標來獲取,那麼可不能夠給參數起一個名字呢,答案是能夠的。Python 爲這種狀況提供了一種參數形式,叫作關鍵字參數

def say_hello(**kwargs):
        print('hello, %s' % kwargs['name'])
        print('you age: %s' % kwargs['age'])

say_hello(name='Dean', age=30)

使用**加一個形參來表示,其值爲一個字典,key爲咱們實參中傳入的變量,value值爲實參中的變量的值。

參數的組合

Python 函數中,以上參數可組合使用。當參數組合使用時,須要注意如下原則:

  • 有默認值的參數須要放在無默認值參數的後邊
  • 當順序參數和可變參數混合使用時,可變參數的取值爲超出順序參數的實參部分,且可變參數在順序參數以後。
  • args 和 *kwargs 是 Python 的慣用寫法,變量名能夠更換。

參數的經常使用排列順序爲,無默認值順序參數、有默認值順序參數、可變參數、關鍵字參數。

def say_hello(name, age=30, *args, **kwargs):
    print(args)
    print(kwargs)

    print('hello, %s' % name)
    print('you age: %s' % age)
    print('address: %s' % kwargs['address'])

say_hello('Dean', 20, address='Beijing')

參數的專遞

咱們在調用函數時,將實參傳遞給了函數的形參,供函數中邏輯代碼使用。那麼在這個過程當中,計算機內存是一個怎麼的過程呢?咱們在學習變量時知道,Python中的變量是其內部存儲值的一個內存地址或者叫作一個引用。在傳入函數時,即是將這個引用傳入了函數。那麼咱們在函數內部修改變量的值時,是否是就修改了外部的變量的值呢?答案是不必定。

在咱們學習基本數據結構時,咱們知道有可變類型(字典、列表、集合)和不可變類型(數值、字符串、元組)。當咱們傳入函數的參數爲可變類型時,函數中的形參使用的內存地址同實參的內存地址,當改變形參的值時,實參的值也相應跟着修改了。當咱們傳入的爲不可變量時,形參會從新分配一塊內存地址保存實參傳給他的值,當形參修改時,實參天然不會修改。

來看下邊的例子:

# func.py 
def say_hello1(name):
    '不可變類型參數'
    name = 'Time'
    print('name: %s' % name )


def say_hello2(user_dict):
    '可變類型參數'
    user_dict['name'] ='Time'
    print('name: %s' % user_dict['name'])

name = 'Dean'
print('name before:', name)
say_hello1(name)
print('name after:', name)

user_dict = {'name':'Dean'}
print('user_dict before:', user_dict)
say_hello2(user_dict)
print('user_dict after:', user_dict)

"""
# 不可變參數,值沒有變
('name before:', 'Dean')
name: Time
('name after:', 'Dean')

# 可變參數,值變了
('user_dict before:', {'name': 'Dean'})
name: Time
('user_dict after:', {'name': 'Time'})
"""

函數做用域

在第三章,咱們學習變量時,知道變量的做用域決定了在哪一部分程序能夠訪問哪一個特定的變量名稱。在Python中,函數會從新開啓一個做用域,當在函數內部定義的變量,在函數外部是沒法訪問的。那麼該變量即是函數的局部變量,函數外部的變量即可成爲全局變量

total = 0 # 這是一個全局變量
# 可寫函數說明
def sum( arg1, arg2 ):
    #返回2個參數的和.
    total = arg1 + arg2 # total在這裏是局部變量.
    print ("函數內是局部變量 : ", total)
    return total

#調用sum函數
sum( 10, 20 )
print ("函數外是全局變量 : ", total)

那麼當內部的局部變量想要暴露出來給外部使用時如何實現呢?Python提供了2個關鍵字,gobalnonlocal

global 將變量做用域變爲函數外層全局做用域。

num = 1
def fun1():
    global num  # 須要使用 global 關鍵字聲明
    print(num) 
    num = 123
    print(num)
fun1()

nonlocal 將變量做用域變爲函數外部非全局變量,及閉包(Enclosing)做用域。

def outer():
    num = 10
    def inner():
        nonlocal num   # nonlocal關鍵字聲明
        num = 100
        print(num)
    inner()
    print(num)
outer()

內建函數

內建函數,是Python中已經定義好的函數能夠在編寫代碼時直接使用。咱們已經使用過內建函數,如lenrange 等。更多的內建函數,可參閱官方文檔中函數說明

匿名函數

匿名函數,就是不使用def來定義的函數。Python中使用關鍵字lambda 來實現匿名函數。

# 語法
lambda [arg1 [,arg2,.....argn]]:表達式

語法說明:

  • arg爲參數,能夠任意多個,使用逗號分隔
  • 表達式 爲函數體,使用冒號開頭
  • 表達式 的返回值即爲函數的返回值

實例:

# 內名函數
sum = lambda arg1, arg2: arg1 + arg2
 
# 調用sum函數
print ("相加後的值爲 : ", sum( 10, 20 ))
print ("相加後的值爲 : ", sum( 20, 20 ))

函數註解

函數註解,爲函數和參數增長了一些說明特性。python3.0 新增的特性,見PEP3107。可經過函數的__annotations__ 熟悉查看。

def f(ham: 42, eggs: int = 'spam') -> "Nothing to see here":
    print("Annotations:", f.__annotations__)
    print("Arguments:", ham, eggs)

f('wonderful')
'''
Annotations: {'eggs': <class 'int'>, 'return': 'Nothing to see here', 'ham': 42}
Arguments: wonderful spam
'''

def foo(a: 'x', b: 5 + 6, c: list) -> max(2, 9):
    pass

語法說明:

  • 參數的說明在參數後邊,使用冒號和參數隔離,註釋爲一個表達式。
  • 函數的註解在函數參數括號後,使用'->' 符號開頭,也是一個表達式。

在Python的編程時,註解使用的比較少,以方便人們更多的使用docstring來講明參數及返回值,另外一方面Python函數參數可進一步經過編碼規範一眼就能看出什麼類型。這種註釋語法,反而顯得囉嗦冗餘。

總結

本章咱們學習了函數及其使用,知識重點總結以下:

  • Python提供了許多內建函數共咱們使用,內建函數可直接使用無需定義。
  • 參數組合在使用的時候是有順序的,依次是無默認值順序參數、有默認值順序參數、可變參數、關鍵字參數。
  • args 表示可變參數,*kwargs 表示關鍵字參數。
  • 當參數爲不可變參數時,函數不會影響外部實參值,當參數爲不可變參數時,函數則會影響外部實參值。
  • 函數自己可做爲參數傳遞。
  • Python 中使用lambda 來實現匿名函數。

練習

  • 一、求n的階乘
def factorial(num):
    """
    求階乘
    :param num: 非負整數
    :return: num的階乘
    """
    result = 1
    for n in range(1, num + 1):
        result *= n
    return result

n = int(input('n = '))
factorial(n)
  • 二、實現判斷一個數是否是素數的函數。
# 素數,在大於1的天然數中,除了1和它自己之外再也不有其餘因數
def is_prime(num):
    for factor in range(2, num):
        if num % factor == 0:
            return False
    return True if num != 1 else False

參考

相關文章
相關標籤/搜索