• 小白学习之路,基础三(函数)


     一,函数的基本介绍

    首先谈到函数,相信大家都不陌生,不管是其他语言都会用到,可能就是叫法不一样。就我知道的跟python中函数类似的,在C中只有function,在Java里面叫做method,在js中也是叫function。函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。

    函数有下面三点好处:

    1.能够减少重复代码的使用

    2.让你的程序有更好的扩展性

    3.可以让你的程序变得更加容易维护

    下面我们就来讲一下怎么定义一个函数

    • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()
    • 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
    • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
    • 函数内容以冒号起始,并且缩进。
    • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

    补充知识:return不返回值的时候有三种方法:不写return,只写一个return,或者return None。return当有多个返回值的时候用逗号分隔。接收的时候可以用一个变量接收(元组),也可以用多个变量接收。

    二,函数的参数

    函数可以传参,也可以不传参,都是可以的哦。

     1 #定义一个需要传参的函数
     2 def say(name):
     3     print('hello',name)
     4 say('zzq')   #调用say这个函数,并且传入参数
     5 
     6 #不需要传参的函数
     7 def take():
     8     print('I Love You')
     9 take()   #调用函数,不传任何参数
    10 
    11 #有返回值的函数
    12 def add(x,y):
    13     return x+y
    14 a=add(4,5) #传入的参数必须是相同数据类型
    15 print(a)   #执行结果为9
    View Code

    值得注意的是在传入的参数还有三种:普通参数,不定长参数,自典型

     1 #普通参数
     2 def say1(name):
     3     print(name)
     4 say1('gmx')
     5 
     6 #不定长参数
     7 def say2(*args):
     8     print(args)
     9 say2(1,5,'sd')
    10 
    11 #自典型
    12 def say3(**kwargs):
    13     print(kwargs)
    14 say3(name='zzq',say='I Love You',to_name='gmx')#传入的参数必须是字典
    15 
    16 #执行结果为
    17 #gmx
    18 #(1, 5, 'sd')
    19 #{'name': 'zzq', 'say': 'I Love You', 'to_name': 'gmx'}
    View Code

    听到参数大家还经常听到形参跟实参这两个词,下面我跟大家大概讲一下两者的区别。

    • 形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
    • 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

    三,全局变量跟局部变量

    什么是全局变量跟局部变量呢,根据他们的名字可以知道,全局变量可以在全局使用,局部变量呢只能在一些地方使用的变量。

    在函数里面定义的变量为局部变量,只能试用于函数。

    在外面定义的叫全局变量,也可以在函数内部访问。

    切记!如果全局变量有一个变量名字跟函数里面的相同,函数内部在调用时,用的是函数内部的变量

     1 name='zzq'
     2 def say():
     3     name='gmx'
     4     print(name)#调用的是函数内部的name
     5 say()
     6 print(name)#调用的全局变量的name
     7 
     8 #执行结果
     9 #gmx
    10 #zzq
    View Code

    在函数中的局部变量也能转化为全局变量,但是这种方法是不推荐使用的,也是不能使用的。

     1 name='zzq'
     2 def say():
     3     global name #把name设置为全局变量
     4     name='gmx'
     5     print(name)
     6 say()
     7 print(name)
     8 #执行结果
     9 #gmx
    10 #gmx
    View Code

    四,匿名函数

    python 使用 lambda 来创建匿名函数,一般一个函数用的次数比较少,为了方便就出现了匿名函数。

    • lambda只是一个表达式,函数体比def简单很多。
    • lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
    • lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
    • 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

    匿名函数基本语法:

    1 #计算数字的平方
    2 calc=lambda n:n*n  #定义一个匿名函数
    3 print(calc(5))
    4 
    5 #当然还能这样用
    6 l=map(lambda n:n*n,[1,2,3,4,5]) #map把后面可迭代对象去执行前面的函数
    7 for i in l:
    8     print(i)

    在这里用到了map,那就简单的提一下把。因为要涉及到后面的迭代对象,所以就简单讲一下用法。

    map函数的原型是map(function, iterable, …),它的返回结果是一个列表。

    参数function传的是一个函数名,可以是python内置的,也可以是自定义的。
    参数iterable传的是一个可以迭代的对象,例如列表,元组,字符串这样的。

    解释起来有点不好理解,下面一些简单的代码例子,供大家参考吧。

     1 a=(1,2,3,4,5)
     2 b=[1,2,3,4,5]
     3 c="zhangkang"
     4 
     5 la=map(str,a)
     6 lb=map(str,b)
     7 lc=map(str,c)
     8 
     9 print(la)
    10 print(lb)
    11 print(lc)
    12 
    13 输出:
    14 ['1', '2', '3', '4', '5']
    15 ['1', '2', '3', '4', '5']
    16 ['z', 'h', 'a', 'n', 'g', 'k', 'a', 'n', 'g']
    View Code

    五,嵌套函数

    嵌套函数,听到名字难道是一个函数里面还可以放函数,卧槽,居然特么还有这种操作?当然,嵌套函数就是一个函数里面还嵌套另外一个函数,下面一个简单的例子,给大家参考理解吧。

     1 name='zzq'
     2 def say1():
     3     name='gmx'
     4     def say2():
     5         name='other'
     6         print('最里面函数',name)
     7     say2()
     8     print('外面一层函数',name)
     9 say1()
    10 print('最外面函数',name)
    11 
    12 #执行结果
    13 #最里面函数 other
    14 #外面一层函数 gmx
    15 #最外面函数 zzq
    View Code

    六,递归

    我们刚刚了解了嵌套函数,知道在函数的内部可以继续调用函数,如果在函数的内部调用自己,那么这个函数就是递归。当然递归不能随便乱用,他也有自己的调用特性。

    递归特性:

    1. 必须有一个明确的结束条件

    2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少

    3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

     1 #输入一个数,输出所有平方小于500的数
     2 def calc(n):
     3     if n>500:
     4         return n
     5     print(n)
     6     return calc(n*n)  #继续调用自己,形成递归
     7 calc(2)
     8 
     9 #执行结果
    10 2
    11 4
    12 16
    13 256
    View Code

    4.阶乘

    在递归的运用中,有一个很经典的例子,那就是计算阶乘的结果。用其他方法也可以实现,但是估计比较麻烦,下面是用简单的递归实现阶乘计算。

    1 def test(x):
    2     if x==1:
    3         return x
    4     else:
    5         return x*test(x-1)

    5.汉诺塔问题

    当然在递归里面很经典的还有一个问题就是汉诺塔问题,而且更能体现递归的好处。

    如下图所示,从左到右有A、B、C三根柱子,其中A柱子上面有从小叠到大的n个圆盘,现要求将A柱子上的圆盘移到C柱子上去,期间只有一个原则:一次只能移到一个盘子且大盘子不能在小盘子上面,求移动的步骤和移动的次数

    解决的思路其实就三步:1.先把n-1个盘子移动到B(借助C),2.最大的那个放在C,3.把n-1个盘子放到C(借助A)

    x = 0  # 记录移动次数
    def hannota(n, A, B, C):
        '''
        :param n: 总共移动盘子个数
        :param A: A柱子
        :param B: B柱子
        :param C: C柱子
        :return:
        '''
        if n > 0:
            hannota(n - 1, A, C, B)  # 把n-1从A进过C移动到B
            global x
            x += 1
            print '%s-->%s' % (A, C)  # 把最大的n从A移动到C
            hannota(n - 1, B, A, C)  # 把剩下的n-1从B通过A移动到C
    hannota(2, "A", "B", "C")
    print x

    七,高阶函数

    变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。通俗的讲就是函数的参数可以是函数,然后里面的参数可以给作为参数的函数当成传入的参数。emmm,好吧,讲得是有点乱。。那就分析分析代码吧

    1 输入ascii的编码号,输出对应的值
    2 def say(letter,f):
    3     return f(letter)
    4 ascii_name=say(65,chr)#f为一个函数
    5 print(ascii_name)
    6 #执行结果
    7 #A
    View Code

    卧槽,不知不觉学了这么多函数了啊,你就会想这个学了有啥子用嘛,放心,这个为后面厉害的装逼的打基础呢,这章的嵌套函数跟高阶函数为后面的装饰器打基础。万丈高楼平地起,所以还是要把基础掌握好,怎么才能更好的掌握呢,当然方法只有一个,那就是多敲,多记,多思考。

  • 相关阅读:
    http之100-continue
    WebHeaderCollection类
    python selenium登陆网易云音乐
    python爬虫多线程编程
    python使用unittest模块selenium访问斗鱼获取直播信息
    python之jsonpath的使用
    python 自定义函数
    Android 中万能的 BaseAdapter(Spinner,ListView,GridView) 的使用!
    Android UI设计
    Android杂谈--ListView之BaseAdapter的使用
  • 原文地址:https://www.cnblogs.com/zzqit/p/9175645.html
Copyright © 2020-2023  润新知