zoukankan      html  css  js  c++  java
  • python初学-函数(廖雪峰)

    一、函数简介

    1. 调用一个函数,需要知道函数的名称和参数(官方文档:http://docs.python.org/3/library/functions.html#abs
    2. 定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回
    3. 空函数:用pass语句:用来作为占位符,让代码能运行起来

    二、函数参数

    1. 把参数的名字和位置确定下来,函数的接口定义就完成了。对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复杂逻辑被封装起来,调用者无需了解
    2. 位置参数:传入的值按照位置顺序依次赋给参数
    3. 默认参数:必选参数在前,默认参数在后;当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数(默认参数可以通过传参替换)
      1)默认参数降低了函数调用的难度,而一旦需要更复杂的调用时,又可以传递更多的参数来实现
      2)按顺序提供默认参数
      3)通过参数名传递指定的默认参数
      4)默认参数要牢记一点:默认参数必须指向不变对象!
    4. 可变参数:传入的参数个数是不确定的(任意个包括0):定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*
      1)可以将list或tuple作为参数传入,传入是前面加*即可
    5. 关键字参数:允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict
    6. 命名关键字参数:
      1)作用:限制关键字参数的名字
      2)命名关键字参数需要一个特殊分隔符**后面的参数被视为命名关键字参数
      3)如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了(注意:使用命名关键字参数时,要特别注意,如果没有可变参数,就必须加一个*作为特殊分隔符)
      4)命名关键字参数必须传入参数名,如果没有传入参数名,调用将报错
      5)命名关键字参数可以有缺省值
    7. 参数组合
      1)在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用
      2)参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数(即:容易变动的往后放)

     示例:

    1、关键字参数:
    def person(name, age, **kw):
        print('name:', name, 'age:', age, 'other:', kw)
    
    2、命名关键字参数:
    def person(name, age, *, city, job):
        print(name, age, city, job)

    3、参数组合
    def f1(a, b, c=0, *args, **kw):
        print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
    
    def f2(a, b, c=0, *, d, **kw):
        print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
     

    三、递归函数

    1. 一个函数在内部调用自身本身,这个函数就是递归函数
    2. 递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
    3. 使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。
    4. 尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况
      (解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的)
    5. 注意:大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把函数改成尾递归方式,也会导致栈溢出

    三、总结

    1. 默认参数一定要用不可变对象,如果是可变对象,程序运行时会有逻辑错误!
    2. 要注意定义可变参数和关键字参数的语法:
      1)*args是可变参数,args接收的是一个tuple;
      2)**kw是关键字参数,kw接收的是一个dict
      3)可变参数既可以直接传入:func(1, 2, 3),又可以先组装list或tuple,再通过*args传入:func(*(1, 2, 3))
      4)关键字参数既可以直接传入:func(a=1, b=2),又可以先组装dict,再通过**kw传入:func(**{'a': 1, 'b': 2})
      5)使用*args**kw是Python的习惯写法,当然也可以用其他参数名,但最好使用习惯用法
    3. 命名的关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值。
    4. 定义命名的关键字参数在没有可变参数的情况下不要忘了写分隔符*,否则定义的将是位置参数。
    5. 使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出
    6. 针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。
    7. Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题

    补充:

    1. 为什么要设计strNone这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误
    2. 由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象
  • 相关阅读:
    开放源码的对象关系映射工具ORM.NET 插入数据 Insert/Update Data
    开放源码的对象关系映射工具ORM.NET 快档开发入门 Quick Start
    .NET 动态脚本语言Script.NET 开发指南
    开放源码的对象关系映射工具ORM.NET 删除数据 Deleting Records using ORM.NET
    .NET Remoting过时了吗?为什么公司的项目还是选择用.NET Remoting,而不是WCF?
    开放源码的对象关系映射工具ORM.NET 查看和显示数据 View and Display data using ORM.NET
    开放源码的对象关系映射工具ORM.NET 查询表 调用存储过程 增加自定义代码
    技术人生:坚持,每日一博
    CQRS:CQRS + DDD + MDP 实现快速应用程序开发
    NodeJs:Happy代码生成器,重构了代码,更新了文档,完善了示例,欢迎下载使用
  • 原文地址:https://www.cnblogs.com/jayce9102/p/12149067.html
Copyright © 2011-2022 走看看