您的位置:首页 > 编程语言 > Python开发

python基础与高级特性(五):函数

2019-05-27 18:07 204 查看

python从入门到坚持

  • 三.变量作用域
  • 四.参数传递
  • 五.匿名函数
  • 六.递归函数
  • 一.为什么需要函数

    如果在开发程序时,需要某块代码多次,但是为了提高编写的效率以及代码的重用,所以把具有独立功能的代码块组织为一个小模块,这就是函数。

    二.函数的创建和调用

    1.函数的定义与调用

    (1)定义一个函数

    def test(a, b):
    "用来完成对2个数求和"
    print("%d" %(a+b))
    
    test(11, 22)
    33

    (2)定义一个空函数
    定义一个空函数,可以用pass语句:
    pass可以用来作为占位符,还没有想好怎么写函数的代码,就可以先方一个pass

    def get_passwd():  #定义函数,不执行代码块
    pass 			#pass只是一个占位符,不做任何操作
    if _name_ == "_main_":
    get_passwd()

    2.查看test函数文档

    help(test)

    3.函数返回值

    所谓的“返回值”,就是程序中函数完成一件事情后,最后给调用者的结果。

    def f2c(fahrenheit):
    """
    将华氏温度转换为摄氏温度
    """
    #计算摄氏度
    celsius = (fahrenheit - 32)/1.8
    return fahrenheit, celsius
    if _name_ == "_main_":
    fahrenheit, celsius = f2c(30)
    print('%.1f华氏度转为摄氏度为%.1f' %(fahrenheit, celsius))

    4.定义函数的格式

    def 函数名(参数1,参数2,’…'参数n):
    函数体
    (1)函数名的命名规则要符合python中的命名要求。一般用小写字母和单下划线、数字等组合;匈牙利命名法(sUserName),驼峰式大小写(userName),帕斯卡命名法(UserName)
    (2)def是定义函数的关键词,这个简写来自英文单词define
    (3)函数名后面是圆括号,括号里面,可以有参数列表,也可以没有参数
    (4)千万不要忘记了括号后面的冒号
    (5)函数体(语句块),相对与def缩进,按照python习惯,缩进四个空格

    5. 函数的优势

    从理论上说,不用函数,也能够编程,我们在前面已经写了程序,就没有写函数,当然,用python的内建函数姑且算了。现在之所以使用函数,主要是:
    (1)降低编程的难度(分而治之的思想)
    (2)代码重用。避免了重复劳动,提高了工作效率。

    三.变量作用域

    1.局部变量

    局部变量:就是在函数内部定义的变量。
    不同的函数,可以定义相同的名字的局部变量,但是各用个的不会产生影响;
    局部变量的作用:为了临时保存数据需要在函数中定义变量来进行存储,这就是它的作用。

    2.全局变量

    全局变量:如果一个变量,既能在一个函数中使用,也能在其他的函数中使用,这样的变量就是全局变量。
    (1)在函数外边定义的变量叫做全局变量
    (2)全局变量能够在所有的函数中进行访问
    (3)如果在函数中修改全局变量,那么就需要使用global进行声明,否则出错
    (4)如果全局变量的名字和局部变量的名字相同,那么使用的是局部变量的
    小技巧:强龙不压地头蛇(就近原则)


    不使用global声明全局变量时不能修改全局变量?
    global的本质是声明可以修改全局变量的指向, 即变量可以指向新的数据。
    1). 不可变类型的全局变量: 指向的数据不能修改, 不使用global时无法修改全局变量。
    2). 可变类型的全局变量: 指向的数据可以修改, 不使用global时可以修改全局变量。

    四.参数传递

    1.形参与实参


    形参:定义时小括号中的参数,用来接收参数用的,称为“形参”
    实参:调用时小括号中的参数,用来传递给函数用的,成为“实参”

    2.参数检查

    调用函数时,如果参数个数不对,python解释器会自动检查出来,并抛出TypeError;如果参数类型不对,python解释器就无法帮我们检查。数据类型检查可以用内置函数isinstance实现。

    3.默认参数

    调用函数时,如果没有指定某个参数将抛出异常,即在定义函数时,直接指出形式参数的默认值。这样,当没有传入参数时,则直接使用定义函数时设置的默认值。定义带有默认值参数的函数语法格式如下:
    def functionname(…, [parameter1 = defaultvalue1])
    [functionbody]

    参数说明:
    functionname:函数名称,在调用函数时使用。
    parameter1 = defaultvalue1:可选参数,用于指定向函数中传递的参数,并且为该参数设置默认值为defaultvalue1。
    functionbody:可选参数,用于指定函数体,即该函数被调用后,要执行的功能代码。
    默认参数注意事项:
    (1)有多个参数时,变化大的放前面,变化小的放后面;
    (2)必选参数在前,默认参数在后。

    def mypow(x: int, y: int = 2) -> int:
    """
    求x的y次方
    :param x:
    :param y:
    :return:
    """
    return x ** y
    
    #
    # mypow(3, 2)
    # mypow(4, 2)
    # 如果传递一个参数, x=3, y没有传递就是默认值2;
    print(mypow(3))
    # 如果传递2个参数, x=3, y有默认值2, 但是3会覆盖默认值,也就是求2的三次方;
    print(mypow(2, 3))

    4.可变参数

    可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个。
    如果已经有一个list或者tuple,要调用一个可变参数怎么办?
    (1)python允许你在list或tuple前面加一个*
    (2)把list或tuple的元素变成可变参数传进去;

    # *nums用来接收多个变量/参数, 接收近来的nums是一个元组;
    def numSquare(*nums):
    """
    求n个数的平方
    :param nums:
    :return:
    """
    # print(nums)
    result = 0
    for num in nums:
    result += pow(num, 2)
    print(result)
    numSquare()
    numSquare(1)
    numSquare(1, 2, 3)
    numSquare(3, 4, 5, 6, 7)
    
    # # *score可以存多个数值;
    # low, *score, high = [1, 2, 3, 4, 5, 6100]
    ###

    5.关键字参数

    关键字参数允许传入0个或任意个含参数名的参数;这些关键字参数在函数内部自动组装为一个底层它;关键字参数用**kwargs;

    # **kwargs: 关键字参数, 接收的kwargs是一个字典;
    def recordStudentInfo(name, sid, **kwargs):
    """
    录入学生信息, 必填的内容姓名和学号, 其他的可以自己输入
    :param name:
    :param sid:
    :return:
    """
    print("""
    
    姓名: %s
    学号: %s
    
    """%(name, sid))
    
    for key, value in kwargs.items():
    print("\t %s: \t%s" %(key, value))
    
    recordStudentInfo("西部开源", '001', score=100, courses=['python', 'c', 'Linux'])

    6.参数组合

    参数组合是指可以必选参数,默认参数,可变参数和关键字参数一起使用。参数定义的顺序必须是:必选参数,默认参数,可变参数和关键字参数。

    7.参数总结

    **对于任意函数,都可以通过类似func(*args,kw)的形式调用它。

    五.匿名函数

    匿名函数:指一类无须定义标示符的函数或子程序。python用lambda语法定义匿名函数,只需要用表达式而无需申明。(省略了用def声明函数的标准步骤)
    lambda函数的语法只包含一个语句,如下:
    lambda[arg1 [,arg2, …argn]] : expression
    lambda函数能接收任何数量的参数,但只能返回一个表达式的值。

    lambda_sum = lambda arg1, arg2 :  arg1+arg2
    print("运行结果: ", lambda_sum(1, 2))
    print("运行结果: ", lambda_sum(3, 5))

    六.递归函数

    递归函数:一个函数在内部调用自己本身,这个函数就是递归函数。
    递归函数原理:

    1.常用的递归函数

    (1)求阶乘

    def recursive_factorial(num):
    """
    使用递归求num的阶乘
    """
    # 如果num等于0或者1, 返回1;
    if num in (0, 1):
    return 1
    # num的阶乘为num*(num-1)!
    else:
    return num * recursive_factorial(num - 1)
    
    print("3的阶乘: ", factorial(3))
    print("6的阶乘: ", factorial(6))
    print("3的阶乘: ", recursive_factorial(3))
    print("6的阶乘: ", recursive_factorial(6))
    print("998的阶乘: ", recursive_factorial(998))

    (2)斐波那契数列

    """
    斐波那契数列(Fibonacci sequence),又称黄金分割数列,指的是这样一个数列:
    1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递推的方法定义:
    F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)
    """
    
    def fib(num):
    """
    斐波那契数列
    :param num:
    :return:
    """
    if num <= 2:
    return 1
    else:
    return fib(num - 1) + fib(num - 2)
    result = fib(4)
    print(result)

    (3)汉诺塔问题

    moveCount = 0
    def hanoi(n, a='A', b='B', c='C'):
    """
    :param n:盘子个数
    :param a:初始塔
    :param b:缓存塔
    :param c:目标塔
    :return:移动次数
    """
    if n == 1:
    global moveCount
    moveCount += 1
    print(a, "--->", c)
    else:
    # 只是调用自己, 并没有真实的移动;
    # 1). 打开冰箱门
    hanoi(n - 1, a, c, b)
    # 2). 把大象放进去
    hanoi(1, a, b, c)
    # 3). 把冰箱门close
    hanoi(n - 1, b, a, c)
    hanoi(3)
    print("移动次数:", moveCount)
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: