Python之路,Day04-函數與模塊

 

本節內容

一、函數的定義python

二、如何使用函數程序員

三、函數的返回值編程

四、使用註釋改進文檔數據結構

五、傳遞任意數量的實參app

六、函數與模塊編程語言

 

 

 

一、函數的定義

函數的通常定義(中學/數學):函數的近代定義是給定一個數集A,假設其中的元素爲x,對A中的元素x施加對應法則f,記做f(x),獲得另外一數集B,假設B中的元素爲y,則y與x之間的等量關係能夠用y=f(x)表示,函數概念含有三個要素:定義域A、值域C和對應法則f。ide

 

編程語言中函數的定義(計算機):函數是邏輯結構化和過程化的一種編程方法。函數

函數的定義方法(案例):oop

>>> def fib(n):    # write Fibonacci series up to n
...     """Print a Fibonacci series up to n.""" ... a, b = 0, 1 ... while a < n: ... print(a, end=' ') ... a, b = b, a+b ... print() """ def:定義函數的關鍵字 flb:函數名 (n):定義函數的參數 """""":文檔描述 代碼塊: a, b = 0, 1 while a < n: print(a, end=' ') a, b = b, a+b print() """

 具體學習:學習

下面打印一個問候的簡單函數:

1 def greet_user():    #定義一個函數,關鍵詞爲"def",函數名爲"greet_user",最後以「:」結尾
2     """顯示簡單的問候語"""    #描述函數的具體功能
3     print("Hello!")         #函數體的代碼塊,用於實現函數功能
4 
5 greet_user()         #調用函數

 注意:(1)在第一行定義函數中,不須要任何信息就能完成工做,所以括號是空的(即使如此,括號必不可少!)

   (2)要調用函數,能夠依次指定函數名以及括號括起的必要信息。在第五行代碼中,由於此函數greet_uesr()括號中不須要任何信息,只須要輸入greet_uesr()便可。和預期效果同樣,打印Hello!:

練習:大腦P149

1 def search4vowels(): 2     vowels = set('aeiou') 3     word = input("Provide a word to search for vowels:") 4     found = vowels.intersection(set(word)) 5     for vowel in found: 6         print(vowel) 7 
8 search4vowels() 9 search4vowels() #能夠重複屢次調用
search_vowels

二、如何使用函數(傳遞實參)

函數的使用方法(先看案例)

>>> def fib2(n):  # return Fibonacci series up to n
...     """Return a list containing the Fibonacci series up to n.""" ... result = [] ... a, b = 0, 1 ... while a < n: ... result.append(a) # see below
...         a, b = b, a+b ... return result ... >>> f100 = fib2(100)    # call it
>>> f100                # write the result
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

 2.1 向函數傳遞信息

針對greet_user()只要稍做修改,就可不只實現Hello,還能夠將用戶名字做爲擡頭:

1 def greet_user(username): 2     """顯示簡單的問候語"""    
3     print("hello,"+username.title()+"!") 4 
5 greet_user("zhichao")

代碼greet_user("zhichao")調用函數greet_user()時,向它傳遞執行print()語句所須要的信息username。

2.2 實參和形參

greet_user(username) #username 爲形參;函數完成其工做時所須要的信息。

greet_user("zhichao") #"zhichao"爲實參;實參是調用函數時傳遞給函數的信息。

形參:形式參數,不是實際存在的,是虛擬變量。在定義函數和函數體的時候使用形參,目的是在函數調用時接收實參

實參:實際參數,調用函數時傳遞給函數的參數,能夠是常量、變量,表達式,函數,傳給形參

區別:形參是虛擬的,不佔用空間,形參變量只有在被調用時才分配內存單元,實參是一個變量,佔用內存空間,數據傳遞單向,實參傳給形參,不能倒過來。

傳遞實參:

一、位置實參(基於實參的順序):

1 #zhichao
2 
3 def describe_pet(animal_type,pet_name): 4     """顯示寵物信息"""
5     print("\nI have a" + animal_type + ".") 6     print("My" + animal_type + "'s name is "+pet_name.title() + ".") 7 
8 describe_pet('hamster','harry') 9 describe_pet('cat','python')  #函數調用屢次是一種效率極高的工做方式

位置實參的順序很重要,請確認函數調用中實參的順序與函數定義形參的順序一致

2 關鍵字參數

1 def describe_pet(pet_name,animal_type="dog",): 2     """顯示寵物信息"""
3     print("\nI have a " + animal_type + ".") 4     print("My" + animal_type + "'s name is "+pet_name.title() + ".") 5 
6 describe_pet(pet_name='harry',animal_type='hamster')  #關鍵字實參
7 describe_pet(pet_name='python',animal_type='cat')  #關鍵字實參

思考1:關鍵字參數是否須要與形參順序一致?

思考2:關鍵字參數和位置參數可否同時存在?

例:

#eg1
def func_test(x,y): print(x) print(y) func_test(x=1,2)      #

#eg2
def func_test(x,y): print(x) print(y) func_test(1,y=2)      #

#eg3
def func_test(x,y,z): print(x) print(y) func_test(1,y=2,3)      #

#結論?

****關鍵參數是不能夠寫在位置參數前面的

2.3 默認值

編寫函數時,能夠給形參指定默認值。

1 def describe_pet(pet_name,animal_type="dog",): 2     """顯示寵物信息"""
3     print("\nI have a " + animal_type + ".") 4     print("My" + animal_type + "'s name is "+pet_name.title() + ".") 5 
6 describe_pet('harry','hamster') 7 describe_pet('python','cat')

 2.4 像函數中傳遞列表:

eg:

 1 #Zhichao
 2 
 3 def greet_users(names):  4     """向列表中的每位用戶都發出簡單的問候"""
 5     for name in names:  6         msg = "Hello, "+name.title() +"!"
 7         print(msg)  8 
 9 usernames = ['hannah','ty','margot'] 10 greet_users(usernames)
greet_users

 

三、函數的返回值

 函數返回的值被稱爲函數的返回值;

在函數中,可用return語句將值返回到調用函數的代碼行;

返回值能將你程序的大部分繁重工做移到函數中去完成,從而簡化主程序。

3.1 返回簡單值

eg(formatted_name1):

1 #zhichao
2 
3 def get_formatted_name(first_name,last_name): 4     """返回整潔的姓名"""
5     full_name = first_name + ' '+ last_name 6     return full_name.title() 7 
8 musician = get_formatted_name('jimi','hendrix') #調用返回值的函數時,須要提供一個變量,用於存儲返回的值
9 print(musician)

 

3.2 讓實參變成可選的

有時候,須要讓實參變成可選的,這樣使用函數的人就只須要在必要時候才提供額外信息。

咱們對:formatted_name1 進行擴展(函數的可擴展性

eg(formatted_name2):

1 def get_formatted_name(first_name,middle_name,last_name): 2     """返回整潔的姓名"""
3     full_name = first_name + ' '+middle_name+' '+ last_name 4     return full_name.title() 5 
6 musician = get_formatted_name('jimi','lee','hendrix') #有些人有中間名
7 print(musician)

有些人不必定有中間名,那麼對函數進行優化:

eg(formatted_name2):

#zhichao

def get_formatted_name(first_name,last_name,middle_name=''):  #複習關鍵字實參放後面
    """返回整潔的姓名"""
    if middle_name: full_name = first_name + ' '+middle_name+' '+ last_name else: full_name = first_name + ' ' + last_name return full_name.title() musician = get_formatted_name('jimi','lee','hendrix') musician1 = get_formatted_name('jimi','hendrix') print(musician) print(musician1)

 

3.3 返回多個值

函數能夠返回任意類型的值,包括列表、字典和集合等較爲複雜的數據結構。

大腦P159:

返回一個值:

return_bool

返回一個集合:

1 # Zhichao
2 
3 def search4vowels(word): 4     """Return a boolean based on any vowels found"""
5     vowels = set('aeiou') 6     found = vowels.intersection(set(word)) 7     return found 8 word = search4vowels('hello Zhichao') 9 print(word)
return_set

返回數據:

1 #Zhichao
2 
3 def search4vowels(word): 4     """Return a boolean based on any vowels found"""
5     vowels = set('aeiou') 6     return vowels.intersection(set(word)) 7 word = search4vowels('hello Zhichao') 8 print(word)
return_value

返回字典:

1 #Zhichao
2 
3 def build_person(first_name,last_name): 4     """返回一個字典,其中包含有關一我的的信息"""
5     person = {'first':first_name,'last':last_name} 6     return person 7 
8 musician = build_person('jimi','hendrix') 9 print(musician)
return_dict

 

4.使用註釋改進文檔

複習python的四種數據類型。

當咱們調用函數時,才知道咱們須要輸入的參數和返回值的類型「type」

對此,咱們的一種解決辦法是把這個信息增長到docstring

python3 註解的記法

1.函數註解是可選的。

2.函數註解能夠提供信息。

 

eg:

1 #zhichao
2 
3 def search4vowels(word:str) ->set: 4     """Return a boolean based on any vowels found"""
5     vowels = set('aeiou') 6     return vowels.intersection(set(word)) 7 
8 help(search4vowels)

 

 5.傳遞任意數量的實參

1. *args,傳入多個參數,轉化成元組。

假如一個函數定義一個披薩的配料,但並不知道有多少配料須要加入,在參數不肯定的狀況下,咱們引入任意數量的實參。

eg:

#Zhichao

def make_pizza(*toppings): """打印顧客點的全部配料"""
    print(toopings) make_pizza("peperoni") make_pizza("mushroom","green peppers","extra cheese")

注意:*toppings的值是一個封裝好的空元組,並將全部接收到的值都封裝在這個元組裏。

 

2.**kwargs,把關鍵字參數,轉化成字典。

eg:

1 # -*- coding:utf-8 -*-
2 # Author:Zhichao
3 
4 def infos(**kwargs): 5     """打印我的信息"""
6     print(kwargs) 7 
8 infos(name="Zhichao",age="24",job="IT")

 

 

 

 設計一個對顧客點披薩進行描述:

 1 #Zhichao
 2 
 3 def make_pizza(*toopings):  4     """概述要製做的披薩"""
 5     print("\nMaking a pizza with the following toppings")  6     for topping in toopings:  7         print("--"+topping)  8 
 9 make_pizza("peperoni") 10 make_pizza("mushroom","green peppers","extra cheese")

 

結合位置實參和任意數量實參:

#Zhichao

def make_pizza(size,*toopings):  #回顧位置實參應放在前面
    """概述要製做的披薩"""
    print("\nMaking a "+str(size)+"-inch pizza with the following toppings") for topping in toopings: print("--"+topping) make_pizza(14,"peperoni") make_pizza(12,"mushroom","green peppers","extra cheese")

 

6.函數與模塊

函數的優勢之一是將代碼與主程序分離;

咱們能夠更進一步,將函數存儲在被稱爲「模塊」的獨立文件中,再將模塊導入主程序;

import語句容許咱們在當前運行的程序文件中使用模塊中的代碼。

優點:

1.經過將函數存儲在獨立的文件中,可隱藏程序代碼的細節,將重點放在程序的高層邏輯上;

2.可讓不一樣的程序中重用函數;

3.可與其餘程序員共享這些文件而不是整個程序;

4.知道如何導入函數能讓你使用其餘程序員編寫的函數庫。

 

6.1 導入整個模塊

模塊是擴展名爲.py的文件(如一些內置的模塊:C:\ProgramData\Anaconda3\Lib)

下面咱們來建立一個模包含函數make_pizza()的模塊。

pizza.py

1 #Zhichao
2 
3 def make_pizza(size,*toopings): 4     """概述要製做的披薩"""
5     print("\nMaking a "+str(size)+"-inch pizza with the following toppings") 6     for topping in toopings: 7         print("--"+topping)

 

接下來,咱們在pizza.py所在目錄下建立一個另外的名爲making_pizzas.py文件,這個文件導入剛建立的模塊,在調用make_pizza()兩次:

making_pizzas.py

1 import pizza #調用模塊
2 
3 pizza.make_pizza(16,'pepperoni')  #調用模塊的函數
4 pizza.make_pizza(12,"mushroom","green peppers","extra cheese")

 

 

 

 6.2 導入特定的函數

能夠導入模塊中的特定函數,方法以下:

1 from module_name import function_name

經過用逗號分開函數名能夠同時導入多個函數:

1 from module_name import function_0,function_1,function_2

對於前面的pizza案例,咱們能夠導入模塊中的特定函數:

1 from pizza import make_pizza 2 make_pizza(16,'pepperoni')  #調用模塊的函數
3 make_pizza(12,"mushroom","green peppers","extra cheese")

若使用此種方法,調用函數時不須要用句點。

 

6.3 使用as 給函數指定別名

思考:若是你導入的函數名與程序中現有的名稱衝突怎麼辦?或者你調用的函數名稱太長怎麼辦?

 

咱們能夠指定函數的另外一個名稱,相似於外號。

下面咱們根據make_pizza指定名稱

1 from pizza import make_pizza as mp 2 mp(16,'pepperoni')  #調用模塊的函數
3 mp(12,"mushroom","green peppers","extra cheese")

通用語法格式:

1 from moudle_name import function_name as fn

 

6.4 使用as給模塊指定別名

eg:

1 import pizza as p 2 
3 p.make_pizza(16,'pepperoni') 4 p.make_pizza(12,"mushroom","green peppers","extra cheese")

通用語法格式:

import moudle_name as mn

 

6.5 導入模塊中的全部函數

使用星號(*)運算符可讓Python導入模塊中的全部函數:

1 #Zhichao
2 from pizza import*
3 
4 make_pizza(16,'pepperoni') 5 make_pizza(12,"mushroom","green peppers","extra cheese")

通用語法格式:

from moudle_name import *

 

Head First Python

大腦P162

使用註解改進文檔:

 

關於註解更多詳細內容參見PEP3107

(https://www.python.org/dev/peps/pep-3107)

大腦 P164

函數:咱們已經知道些什麼

* 函數是命名的代碼塊。

* def關鍵字用來命名函數,函數代碼在def關鍵字下(相對於def關鍵字)縮進

* Python的三重引號字符串能夠用來函數增長多行註釋。若是採用這種方式,他們稱之爲docstring

* 函數能夠接受任意多個命名參數

* return語句容許函數返回任意值(也能夠不反回任何值)

*函數註解能夠用來描述函數參數的類型

 

創建一個通用的函數:

 1 #Zhichao
 2 
 3 def search4vowels(phrase: str) -> set:  4     """return any vowels found in a supplied phrase"""
 5     vowels = set('aeiou')  6     return vowels.intersection(set(phrase))  7 
 8 def search4letters(phrase:str,letters:str)->set:  9     """return a set of the 'letters' found in 'phrase'. """
10     return set(letters).intersection(set(phrase)) 11 
12 help(search4letters) 13 print(search4letters('hitch-hiker','aeiou')) 14 print(search4letters('galaxy','xyz'))

 

 

函數補充:

函數能夠調用函數嗎?

函數引用

eg:

 1 # Author:Zhixhao
 2 
 3 def search4letters(phrase:str,letters:str)->set:  4     """return a set of the 'letters' found in 'phrase'. """
 5     logger("search4letters")  6     return set(letters).intersection(set(phrase))  7 
 8 def logger(source):  9     print("from %s"%source) 10 help(search4letters) 11 
12 print(search4letters('hitch-hiker','aeiou')) 13 print(search4letters('galaxy','xyz'))

 

局部變量與全局變量以及其做用域:

 1 #Zhichao
 2 
 3 school = "中山大學"
 4 
 5 def change_name(name:str):  6     """修更名字"""
 7     # global school
 8     school = "中山大學南方學院"
 9     print("before change",name,school) 10     name = name.title()         #局部變量,能夠理解這個函數就是這個變量的做用域
11     # age = 18
12     print("after change",name) 13 
14 # print("age",age)
15 name = "zhichao"
16 change_name(name) 17 print(name,school)

 

不建議使用  global 在函數內部修改全局變量,容易致使邏輯混亂不清

再來看一個例子:

1 # Author:Zhichao
2 
3 names = ["Marry","Jack","Lin"] 4 def change_name(): 5     names.append("Zhichao") 6     print("inside func",names) 7 
8 change_name() 9 print(names)

請閱讀大腦P185-p187

並嘗試理解:

 

 

總結:

可變:列表、字典和集合

不可變:字符串、整數和元組

(回顧字典的key命名)

 

遞歸:

1 def calc(n): 2     print(n) 3     if int(n/2) == 0: 4         return n 5     return calc(int(n/2)) 6 
7 calc(10)

 

遞歸特性:

1.必須有一個明確的結束條件

2.每次進入更深一層遞歸時,問題規模相比上次遞歸應有所減小。

3.遞歸效率不高,遞歸次數過多會致使棧溢出(在計算機中,函數調用是經過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會多加一層棧幀,每當函數返回,棧就會減小一層棧幀。因爲棧的大小不是無限的,因此,遞歸調用的次數過多,會致使棧溢出。)

相關文章
相關標籤/搜索