一、函数的定义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() #能够重复屡次调用
函数的使用方法(先看案例)
>>> 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]
针对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。
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) #? #结论?
****关键参数是不能够写在位置参数前面的
编写函数时,能够给形参指定默认值。
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')
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)
函数返回的值被称为函数的返回值;
在函数中,可用return语句将值返回到调用函数的代码行;
返回值能将你程序的大部分繁重工做移到函数中去完成,从而简化主程序。
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)
有时候,须要让实参变成可选的,这样使用函数的人就只须要在必要时候才提供额外信息。
咱们对: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)
函数能够返回任意类型的值,包括列表、字典和集合等较为复杂的数据结构。
大脑P159:
返回一个值:
返回一个集合:
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)
返回数据:
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)
返回字典:
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)
复习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)
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")
函数的优势之一是将代码与主程序分离;
咱们能够更进一步,将函数存储在被称为“模块”的独立文件中,再将模块导入主程序;
import语句容许咱们在当前运行的程序文件中使用模块中的代码。
优点:
1.经过将函数存储在独立的文件中,可隐藏程序代码的细节,将重点放在程序的高层逻辑上;
2.可让不一样的程序中重用函数;
3.可与其余程序员共享这些文件而不是整个程序;
4.知道如何导入函数能让你使用其余程序员编写的函数库。
模块是扩展名为.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")
能够导入模块中的特定函数,方法以下:
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")
若使用此种方法,调用函数时不须要用句点。
思考:若是你导入的函数名与程序中现有的名称冲突怎么办?或者你调用的函数名称太长怎么办?
咱们能够指定函数的另外一个名称,相似于外号。
下面咱们根据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
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
使用星号(*)运算符可让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 *
大脑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)这种数据结构实现的,每当进入一个函数调用,栈就会多加一层栈帧,每当函数返回,栈就会减小一层栈帧。因为栈的大小不是无限的,因此,递归调用的次数过多,会致使栈溢出。)