• Python之路,Day04-函数与模块


     

    本节内容

    1、函数的定义

    2、如何使用函数

    3、函数的返回值

    4、使用注释改进文档

    5、传递任意数量的实参

    6、函数与模块

    1、函数的定义

    函数的一般定义(中学/数学):函数的近代定义是给定一个数集A,假设其中的元素为x,对A中的元素x施加对应法则f,记作f(x),得到另一数集B,假设B中的元素为y,则y与x之间的等量关系可以用y=f(x)表示,函数概念含有三个要素:定义域A、值域C和对应法则f。

    编程语言中函数的定义(计算机):函数是逻辑结构化和过程化的一种编程方法。

    函数的定义方法(案例):

    >>> 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

    2、如何使用函数(传递实参)

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

    >>> 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、位置实参(基于实参的顺序):

    1 #zhichao
    2 
    3 def describe_pet(animal_type,pet_name):
    4     """显示宠物信息"""
    5     print("
    I 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("
    I 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("
    I 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

    3、函数的返回值

     函数返回的值被称为函数的返回值;

    在函数中,可用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("
    Making 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("
    Making 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:ProgramDataAnaconda3Lib)

    下面我们来创建一个模包含函数make_pizza()的模块。

    pizza.py

    1 #Zhichao
    2 
    3 def make_pizza(size,*toopings):
    4     """概述要制作的披萨"""
    5     print("
    Making 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)这种数据结构实现的,每当进入一个函数调用,栈就会多加一层栈帧,每当函数返回,栈就会减少一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。)

     

     
  • 相关阅读:
    mysql practice
    image update to ubuntu18.04
    C++11 new feature
    bazel remote executor--- buildfarm( in docker)
    python3学习笔记13(数据结构)
    python3学习笔记12(变量作用域)
    python3学习笔记11(函数)
    jmeter 01 之beanshell preprocessor
    python3学习笔记10(迭代器和生成器)
    python3学习笔记十(循环语句)
  • 原文地址:https://www.cnblogs.com/xuzhichao/p/11570285.html
Copyright © 2020-2023  润新知