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)这种数据结构实现的,每当进入一个函数调用,栈就会多加一层栈帧,每当函数返回,栈就会减小一层栈帧。因为栈的大小不是无限的,因此,递归调用的次数过多,会致使栈溢出。)

相关文章
相关标签/搜索