7.Python函数

作者: 陶不渊 | 来源:发表于2018-10-10 11:04 被阅读3次

    1.定义一个函数

    定义一个函数需要5个部分:

    • def告诉Python,用户在自定义函数
    • function_name告诉Python要定义的函数的名字,且取名尽量做到descriptive
    • (parameters)这是形式参数,简称形参,接收函数调用时,传过来的实参,不需要传参时可省略
    • '''docstring'''不执行任何功能,仅用来说明函数功能,调用函数者可以查看该函数的docstring以了解其功能
    • function_body是函数的主体,函数要实现的功能由它决定

    格式:

    #函数定义
    def function_name(parameters):  #注意冒号
        '''docstring''' #注意缩进1个tab
        function_body   #注意缩进1个tab
    
    #函数调用   
    function_name(arguments)    #arguments为实参,字符串参数要加引号
    

    2.参数

    在上述的函数定义格式中,有两种参数,分别是:parametersarguments

    parameters为形式参数,简称为形参在函数定义时,仅作为符号,表示这里应该有这样一个参数,实现函数的成功定义。

    arguments实参,即主程序中,需要调用函数处理的实实在在的信息。调用时,会实现parameter_1=argument_1...,将所有实参的值赋给对应的形参,交由函数处理。

    例:

    输入:

    def greet_user(username):
        '''display a simple greeting'''
        print('hello, '+username.title()+'!')
        
    greet_user('jack')
    

    输出:

    c:\py>function_define
    hello, Jack!
    

    3.传送多个参数

    上面的例子是仅传一个参数的情况,parameters和arguments可以有多个,有3种方法实现多参数传送。

    (1) 位置实参

    def语句

    def function_name(parameter_1, parameter_2,..., parameter_n):

    调用函数语句

    function_name(argument_1, argument_2,..., argument_n):

    调用函数语句中的实参与def语句中的形参按顺序一一对应,传参时实现的操作如下:

    parameter_1=argument_1
    parameter_2=argument_2
    .
    .
    .
    parameter_n=argument_n
    

    注意,使用位置实参时,一定要按照定义函数时,正确的顺序排列,不然会出错。

    (2) 关键字实参

    关键字传参是将一个name-value组合传给函数形参。

    调用形式:
    function_name(name_1=value_1,name_2=value_2,...,name_n=value_n)

    name-value里面,name为函数定义时,形参的名字,value为主程序中实参的值,通过name=value实现传参。所以通过关键字实参传参,并不需要按照定义时的顺序。

    输入:

    def describe_pet(animal_type,pet_name):
        '''display information about a pet'''
        print('\nI have a '+animal_type+'.')
        print('My '+animal_type+"'s name is "+pet_name+'.')
    
    describe_pet(animal_type='dog',pet_name='harry')
    #顺序不一样
    describe_pet(pet_name='harry',animal_type='dog')
    

    输出:

    c:\py>describe_pet.py
    
    I have a dog.
    My dog's name is harry.
    
    I have a dog.
    My dog's name is harry.
    

    上面程序调用了两次describe_pet函数,参数顺序不一样,但是输出结果一样。

    (3) 默认值

    当一个函数被调用时,它的某些参数总是很少改变时,我们可以给这些很少变动的参数,在定义函数时,给它们一个默认值。这样在调用函数时,若与默认值相同,则可以不用写该参数的实参值,直接采用默认值,如果与默认值不符,可以用关键字name-value对传参。

    输入:

    def describe_pet(pet_name,animal_type='dog'):       #默认animal_type参数值为‘dog’
        '''display information about a pet'''
        print('\nI have a '+animal_type+'.')
        print('My '+animal_type+"'s name is "+pet_name+'.')
    
    describe_pet(pet_name='harry')  #省略animal_type参数值
    describe_pet('harry')   #采用位置实参传参
    
    describe_pet(animal_type='cat',pet_name='tom') #与默认值不符,用name-value对传参
    

    输出:

    c:\py>describe_pet.py
    
    I have a dog.
    My dog's name is harry.
    
    I have a dog.
    My dog's name is harry.
    
    I have a cat.
    My cat's name is tom.
    

    注意: 所有带有默认值的参数必须放在没有默认值的参数后面,不然程序会报错。

    错误示例:

    def describe_pet(animal_type='dog',pet_name):   
    

    输出:

    c:\py>describe_pet.py
      File "C:\py\describe_pet.py", line 1
        def describe_pet(animal_type='dog',pet_name):  
    

    把带默认值的参数放最后,这样也可以使用位置实参来传送参数,忽略后面有默认值的形参,剩下的与调用语句中的实参一一对应。

    (4) 可选实参

    我们可以在定义函数时,把可选参数的默认值设为空optional argument='',这样在调用函数时,即使没有对应的实参,也不会因为实参与形参数量不匹配而报错。

    输入:

    def get_formatted_name(first_name,last_name,middle_name=''):        #给middle_name赋值为空
        '''return a full name,neatly formatted.'''
        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('jimmi','fallon')
    print(musician)
        
    musician = get_formatted_name('jimmi','fallon','lee')   #lee放最后,与middle_name相对应
    print(musician)
    

    输出:

    c:\py>get_formatted_name2
    Jimmi Fallon
    Jimmi Lee Fallon
    

    注意: 上例中的middle_name的默认值为空字符串,因为有默认值,要把它放到最后。Python认为空字符串的值为0,所以if检测到空字符串,即if=0,条件不成立,if下面缩进的语句不执行,转而执行else下面缩进的语句。

    4.返回值

    Python可以返回任意类型的值。

    (1) 返回简单值

    我们调用函数后,在函数末尾使用return语句,可以返回被调用的函数中需要的值;在主程序中,可以使用一个赋值语句接收返回值。

    输入:

    def get_formatted_name(first_name,last_name):
        '''return a full name, neatly formatted.'''
        full_name = first_name+' '+last_name
        return full_name.title()
    musician = get_formatted_name('jimmy','logan') #用musician来接收返回值
    print(musician)
    

    输出:

    c:\py>get_formatted_name.py
    Jimmy Logan
    

    (2) 返回字典

    输入:

    def get_formatted_name(first_name,last_name):
        '''return a dictionary of information about a person.'''
        person={'first':first_name , 'last':last_name}
        return person
        
    musician = get_formatted_name('jimmy','logan')
    print(musician)
    

    输出:

    c:\py>get_formatted_name.py
    {'first': 'jimmy', 'last': 'logan'}
    

    5.处理列表

    (1) 传递列表

    可以将一部分列表处理流程分离出来,作为函数,此时,函数中的形参应该是一个列表,在函数中,也作为一个列表进行处理。在主程序中,传送的实参也必须是一个列表。

    输入:

    def greet_users(names): 
        '''Print a simple greeting to each user in the list.'''
        for name in names:
            msg = 'hello, '+name.title()+'!'
            print(msg)
    
    usernames=['jack','tom','lucy']
    greet_users(usernames)
    

    输出:

    c:\py>greet_users
    hello, Jack!
    hello, Tom!
    hello, Lucy!
    

    (2) 调整列表

    调用函数处理列表,给列表带来的变化是永久的。

    没有使用函数的程序:

    #Start with some designs that need to be printed.
    unprinted_designs = ['iphone case' , 'robot pendant' , 'dodecahedron']
    completed_models = []
    
    #Simulate printing each design, until none are left.
    #Move each design to completed_models after printing.
    while unprinted_designs:
        current_design=unprinted_designs.pop()
        #Simulate creating a 3D print from the design.
        print('printing model: '+current_design)
        completed_models.append(current_design)
    
    #Display all completed models.
    print("\nThe following models have been printed : ")
    for completed_model in completed_models:
        print(completed_model)
    

    输出:

    c:\py>print_model
    printing model: dodecahedron
    printing model: robot pendant
    printing model: iphone case
    
    The following models have been printed :
    dodecahedron
    robot pendant
    iphone case
    

    我们可以把print_modelsshow_completed_models作为两个函数封装起来。

    使用函数的程序:

    def  print_models(unprinted_designs,completed_models):
    #Simulate printing each design, until none are left.
    #Move each design to completed_models after printing.
        while unprinted_designs:
            current_design=unprinted_designs.pop()
            #Simulate creating a 3D print from the design.
            print('printing model: '+current_design)
            completed_models.append(current_design)
    
    def show_completed_models(completed_models):
    #Display all completed models.
        print("\nThe following models have been printed : ")
        for completed_model in completed_models:
            print(completed_model)
            
    #Start with some designs that need to be printed.
    unprinted_designs = ['iphone case' , 'robot pendant' , 'dodecahedron']
    completed_models = []
    
    print("\nunprinted_designs : "+str(unprinted_designs)+'\n')
    print_models(unprinted_designs,completed_models)
    show_completed_models(completed_models)
    print("\ncompleted_models : "+str(completed_models))
    

    输出:

    c:\py>print_model
    
    unprinted_designs : ['iphone case', 'robot pendant', 'dodecahedron']
    
    printing model: dodecahedron
    printing model: robot pendant
    printing model: iphone case
    
    The following models have been printed :
    dodecahedron
    robot pendant
    iphone case
    
    completed_models : ['dodecahedron', 'robot pendant', 'iphone case']
    

    注意: 调用函数处理列表,给列表带来的变化是永久的,就算函数里的形参列表名与主程序中的实参列表名不一致,实参列表依然与形参列表同步变化。

    (3) 用切片使函数不改变列表

    function_name(list_name[:])

    list_name[:]将列表复制一份,作为参数传给函数,所有的操作只会改变切片,不会改变列表本身。

    上例中如果我们不想改变unprinted_designs[:]列表,我们可以用下面的语句来调用函数。

    print_models(unprinted_designs[:],completed_models)
    

    6.特殊的传参情况

    (1) 传递任意数量参数

    def function_name( *parameters )

    在定义函数时,给形参名字前面加上一个‘ * ’号,这时,python会建立一个与形参名同名的元组,将调用函数时传过来的实参,统统保存到元组中。

    输入:

    def make_pizza(*toppings):
        '''print the list of toppings that have been requested.'''
        print(toppings)
    
    make_pizza('pepperoni')
    make_pizza('mushrooms','green peppers','extra cheese')
    

    输出:

    c:\py>make_pizza
    ('pepperoni',)
    ('mushrooms', 'green peppers', 'extra cheese')
    

    (2) 同时传送位置实参与任意数量实参

    和带默认值的形参一样,接收任意数量实参的参数放在位置参数后面

    输入:

    def make_pizza(size,*toppings):
        '''summarize the pizza we are about to make.'''
        print('\nmaking a '+str(size)+'-inch pizza with the following toppings')
        for topping in toppings:
            print('- '+topping)
    
    make_pizza(16,'pepperoni')
    make_pizza(12,'mushrooms','green peppers','extra cheese')
    

    输出:

    c:\py>make_pizza
    
    making a 16-inch pizza with the following toppings
    - pepperoni
    
    making a 12-inch pizza with the following toppings
    - mushrooms
    - green peppers
    - extra cheese
    

    (3) 同时传送位置实参和任意数量关键字实参

    只在传送不定数量的关键字实参时使用。

    def function_name( **parameters )

    在定义函数时,给形参名字前面加上一个‘ ** ’号,这时,python会建立一个与形参名同名的字典,将调用函数时传过来的实参nam-value对,以name作为键,以value作为值,保存到字典中。

    用“ ** ”表示任意数量关键字参数,并将任意数量关键字实参放在最后

    输入:

    def build_profile(first,last,**user_info):
        '''build a dictionary containing everything we know about a user.'''
        profile = {}
        profile['first_name'] = first
        profile['last_name'] = last
        for key,value in user_info.items():
            profile[key] = value
        return profile
    user_profile = build_profile('albert','einstein',
                                                    location='princeton',
                                                    field='physics')
    print(user_profile)
    

    输出:

    c:\py>build_profile
    {'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics'}
    

    7.while语句和函数

    输入:

    def get_formatted_name(first_name,last_name):
        '''return full name'''
        person=first_name+' '+last_name
        return person
    
    while True:
        print('\nplease tell me your name:')
        print("(enter 'q' to quit)")
        f_name=input('First_name : ')
        if f_name == 'q':       #输入q退出程序
            break
        l_name=input('Last_name : ')
        if l_name == 'q':
            break
        formatted_name = get_formatted_name(f_name,l_name)
        print("Full_name : "+formatted_name)
    

    输出:

    c:\py>get_formatted_name
    
    please tell me your name:
    (enter 'q' to quit)
    First_name : jimmy
    Last_name : logan
    Full_name : jimmy logan
    
    please tell me your name:
    (enter 'q' to quit)
    First_name : tao
    Last_name : ming
    Full_name : tao ming
    
    please tell me your name:
    (enter 'q' to quit)
    First_name :
    

    使用while,我们可以循环调用函数。

    8.模块

    将函数存储在不同的文件中,可以让我们忽略程序执行的一些细节,只关注更高的逻辑。

    原程序:

    def make_pizza(size,*toppings):
        '''summarize the pizza we are about to make.'''
        print('\nmaking a '+str(size)+'-inch pizza with the following toppings')
        for topping in toppings:
            print('- '+topping)
    
    make_pizza(16,'pepperoni')
    make_pizza(12,'mushrooms','green peppers','extra cheese')
    

    将函数make_pizza作为模块独立出来。

    如下:

    def make_pizza(size,*toppings):
        '''summarize the pizza we are about to make.'''
        print('\nmaking a '+str(size)+'-inch pizza with the following toppings')
        for topping in toppings:
            print('- '+topping)
    

    将主程序文件和模块文件放在同一个目录下。

    (1) 用import导入整个模块

    格式: import module_name

    主程序:

    import pizza        #导入整个pizza模块
    
    pizza.make_pizza(16,'pepperoni')  #
    pizza.make_pizza(12,'mushrooms','green peppers','extra cheese')
    

    输出:

    making a 16-inch pizza with the following toppings
    - pepperoni
    
    making a 12-inch pizza with the following toppings
    - mushrooms
    - green peppers
    - extra cheese
    

    import pizza语句会让Python将pizza模块中所有代码复制到主程序开头,使主程序可以使用pizza模块中,所有的函数。

    注意: 直接导入整个模块,调用pizza模块中的函数时,需要用一个‘ . ’将模块名和函数名间隔开,格式如下:

    module_name.function_name()

    (2)导入特定的函数

    格式:from module_name import function_name

    此时调用函数时不需要‘ . ’来隔开模块名与函数名。

    输入:

    from pizza import make_pizza        #只导入pizza模块中的make_pizza函数
    
    make_pizza(16,'pepperoni')
    make_pizza(12,'mushrooms','green peppers','extra cheese')
    

    输出:

    making a 16-inch pizza with the following toppings
    - pepperoni
    
    making a 12-inch pizza with the following toppings
    - mushrooms
    - green peppers
    - extra cheese
    

    输出与上面的例子相同。

    注意: 由于此时只导入特定的函数,所以主程序调用时,不加‘.’号来表示模块中的某个函数。

    (3) 使用as给函数起别名

    如果导入的函数的名字与主程序中的函数名冲突,又或者导入的函数名太长,我们可以用关键字as给函数起个别名,主程序可以用别名调用函数。

    格式:from module_name import function_name as alias

    输入:

    from pizza import make_pizza as mp  #给make_pizza函数起别名为mp
    
    mp(16,'pepperoni')      #使用mp调用函数
    mp(12,'mushrooms','green peppers','extra cheese')
    

    其输出与上例相同。

    (4) 使用as给模块起别名

    格式:import module_name as alias

    输入:

    import pizza as p   #给pizza模块起别名为p
    
    p.make_pizza(16,'pepperoni')        #使用mp调用函数
    p.make_pizza(12,'mushrooms','green peppers','extra cheese')
    

    输出与上例相同。

    给模块起简单的别名,可以简化程序,让程序作者将注意力放在描述性强的函数名上。

    注意: 这种方法起别名,调用函数时。依然要用‘ . ’将别名与函数名分开。

    (5) 导入模块中所有的函数(不推荐)

    格式:from pizza imporet *

    输入:

    from pizza  import *    #导入所有pizza模块中的函数
    
    make_pizza(16,'pepperoni')
    make_pizza(12,'mushrooms','green peppers','extra cheese')
    

    输出与上例相同。

    导入模块中所有的函数后,我们调用函数,就不需要写模块名和‘ . ’,直接使用函数名,但是,如果模块中有和主程序函数名冲突的,往往会造成不可预料的错误。所以不推荐这种导入方法。

    9.函数编写风格

    (1) 函数的参数赋值,‘=’号两边不留空格

    默认值: def function_name(parameter_0,parameter_1='default value')

    关键字实参: function_name(value_0,parameter_1='value_1')

    (2) 参数字符超过79个

    当参数过多时,我们可以将参数拆成多行。

    格式:

    def function_name(
            parameter_0,parameter_1,parameter_2,        #前面两个tab
            parameter_3,parameter_4,parameter_5):       #前面两个tab
        function body       #前面一个tab
    

    相关文章

      网友评论

        本文标题:7.Python函数

        本文链接:https://www.haomeiwen.com/subject/bhcpaftx.html