zoukankan      html  css  js  c++  java
  • Python 全栈开发四 python基础 函数

    一、函数的基本语法和特性

    函数的定义

    函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的。函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可。

    python中函数的分类

    1. 内置函数
    2. 自定义函数

    特性:

    1. 减少重复代码
    2. 使程序有更好的扩展性
    3. 让程序更容易维护

    定义一个函数

    你可以定义一个由自己想要功能的函数,以下是简单的规则:

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

     函数的语法

     1 #函数
     2 def fun1(a,b):      #a,b 是指形参       
     3     '''fun1'''
     4     print('in the fun1')
     5     return 0
     6 
     7 #注意函数是有返回值的
     8 #过程
     9 def fun2():
    10     '''fun2'''
    11     print('in the fun2')
    12 #没有返回值的函数我们一般让我是函数的过程
    13 #函数式编程就是这种模式

    二、函数的参数

    参数:

    首先说明,在python中,函数定义好后是存放在内存里面的,类似我们通常所说的变量。而形参没有任何实际意义,只有在被调用的时候才会分配内存单元,而函数调用结束后则会被释放;而实参可以是常量,变量、表达式、函数等,实参被调用时必须得有确定的值,这样才可以把这些值传给形参。

    参数的分类:形参,默认参数,不定长参数,关键字参数

    默认参数:即有些情况下,一些参数必须提供,默认的情况下是一个固定的值,只有在少数情况下会修改,这种情况可以选择默认参数。

    不定长参数:在定义函数时,不确定用户需要传入多少个参数,这时使用不定长参数。

    关键字参数:一般情况下,传入参数必须按照给定的参数顺序传入,若不一定知道参数的顺序,可以使用关键字参数来传入。

    注意:在传入参数的时候位置参数必须在关键字参数的前面。

     1 ##参数形式
     2 #1不传参
     3 def fun1():
     4      print('不能传参数')
     5 
     6 
     7 #2必备参数
     8 def fun2(a):
     9      print('必须传参数:',a)
    10 
    11 
    12 #3默认参数
    13 def fun3(b=2):
    14      print('默认参数:',b)  #可传可不传,  注意默认参数必须是不可变的元素即,b必须是不可变的参数
    15 #可选参数
    16 def fun4(*arg):  
    17      print('可传0个到多个:',arg)#可传0个到多个 包装成元组
    18 #fun4(*[1,2])    加个* ,就把里面的壳去掉(解包)
    19 
    20 
    21 
    22 #关键字参数
    23 #定义的时候是跟必备参数一样的
    24 #必须放到最后
    25 
    26 def fun6(**kwarg):
    27      print('关键字参数',kwarg)# 可传0个到多个 包装成字典
    28 #fun6(a=1,b=2)  遵循变量命名规则
    29 #fun6(**{'a':1})   必须是字符串
    30 
    31 
    32 ##参数混合的时候   关键字参数放最后 根据定义的顺序 确保必备参数只能拿到值,并且只能一个
    33 #必备参数+默认参数
    34 def fun7(a,b=1):   #默认参数必须在必备参数的后面
    35      print(a,b)
    36      
    37 def fun8(b,m=1,*a):
    38      print(b)
    39      print(m)
    40      print(a)
    41 
    42 def fun8(*a,b,m):  #尽量不用这种方式,这种方式需要用关键字的方式传入参数
    43      print(a,b,m)
    44      print(b)
    45 
    46 def fun9(*a,b,m=1):
    47      print(a,b,m)
    48      print(b)

    一般情况下按照以下形式传入参数:这样更容易理解程序。

     1 def fun1(x,y=2):
     2     print(x)
     3     print(y)
     4 
     5 # fun1(1)      #默认参数,在调用函数的时候可以不传参
     6 # fun1(1,3)     #也可以选择传参
     7 
     8 def fun2(*args):   #不定长参数,当不确定参数的长度时用不定长参数
     9     print(args)
    10 
    11 # fun2(1,3,4,5,'d')
    12 
    13 def fun3(**kwargs):#关键字参数,接受N个关键字参数,并把它们转换为字典
    14     print(kwargs)
    15 
    16 fun3(i = 'lll')
    17 
    18 def fun4(a,b = 1,*args,**kwargs):
    19     print(a)
    20     print(b)
    21     print(args)
    22     print(kwargs)
    23 fun4(1,2,3,3,3,x = 'lll')   #传参的时候关键字参数必须在位置参数后面

    变量:

    在函数中,变量分为全局变量和局部变量。

    在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。

    全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。

    当全局变量与局部变量同名时:

    在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。

     1 school = 'oleboy'  #全局变量
     2 
     3 def charge_school():
     4     school = 'TANZHOU'   #在函数里面是一个局部变量
     5     print(school)
     6 # charge_school()
     7 # print(school)
     8 #上面可以看出,在调用函数后,函数外部并没有改变school的值
     9 
    10 def charge_school2():
    11     global school
    12     school = 'TANZHOU'
    13     print(school)
    14 charge_school2()
    15 print(school)
    16 #重上面看出,当申明global之后,函数内的变量成为了全局变量,在函数
    17 #内也可以进行访问并修改,在日常工作中做好不要这么做
    18 
    19 
    20 names = ['Alex','Jack','Wallace']
    21 name_tuple= (1,2,3,4)
    22 
    23 def charge_name():
    24     names[1]='金角大王'
    25     print(names)
    26 charge_name()
    27 print(names)
    28 
    29 '''从上可看出,当函数内的变量和全局变量为可变对象时,在函数内可以对其进行修改
    30 '''
    31 a = 1   #全局变量
    32 
    33 def fun():
    34     global a
    35     a = 2   #局部变量,正常情况下无法修改全局变量,若要修改用global  最好不要这么做
    36     print(a)
    37 
    38 print(a)
    39 b = fun()
    40 print(a)

    虽然在实例上,通过global可以将一个局部变量声明为全局变量,但是这种方式对于代码的可维护上非常不好,尽量避免这种操作。

    三、返回值

    函数的返回值可以是大多数的数据类型,也可以是变量名,函数名也可以是函数本身:

    1 def text1():
    2     print('in the text1')
    3     return 0,{0,1},[0,1,3]
    4 
    5 def text2():
    6     return text1  返回的是函数
    7 
    8 y = text2()()  #可以进行调用

    四、嵌套函数

    嵌套函数指的是,函数内定义另一个函数例:

    1 def fun1():
    2     print("fun1")
    3     def fun2():
    4        print("fun2")
    5     fun2()
    6 >>a = fun1()
    7 fun1  #先调用fun1,在fun1里面调用fun2
    8 fun2

    嵌套函数的具体用法将会在后面的学习中提到。

    五、递归

    递归函数是指函数内部调用自己,这样的函数就是递归函数。

    1 def fun1(n):
    2     if n == 1:
    3         return 1      #递归的结束条件
    4     else:
    5         return fun1(n-1)+1
    6 >>print(fun1(3))
    7 3

    递归的必备条件:

    1. 必须有一个明确的结束条件
    2. 每次进入更深层递归时,问题的规模相比上次递归都应有所减少

    递归的局限性:

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

    递归的应用,二分法查找:

     1 data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35]
     2 
     3 def binary_search(dataset,find_num):
     4     print(dataset)
     5 
     6     if len(dataset) >1:
     7         mid = int(len(dataset)/2)
     8         if dataset[mid] == find_num:  #find it
     9             print("找到数字",dataset[mid])
    10         elif dataset[mid] > find_num :# 找的数在mid左面
    11             print("33[31;1m找的数在mid[%s]左面33[0m" % dataset[mid])
    12             return binary_search(dataset[0:mid], find_num)   #再次调用原函数
    13         else:# 找的数在mid右面
    14             print("33[32;1m找的数在mid[%s]右面33[0m" % dataset[mid])
    15             return binary_search(dataset[mid+1:],find_num)
    16     else:
    17         if dataset[0] == find_num:  #find it
    18             print("找到数字啦",dataset[0])
    19         else:
    20             print("没的分了,要找的数字[%s]不在列表里" % find_num)
    21 
    22 >>binary_search(data,66)
    23 [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35]
    24 找的数在mid[18]右面
    25 [20, 21, 22, 23, 30, 32, 33, 35]
    26 找的数在mid[30]右面
    27 [32, 33, 35]
    28 找的数在mid[33]右面
    29 [35]
    30 没的分了,要找的数字[66]不在列表里

    六、匿名函数

    匿名函数没有函数名,一般情况就是只调用一次,后续不会再调用。

     1 cala = lambda n:n*n  #一般用于只调用一次
     2 '''
     3 n:就是函数的形参
     4 n*n:就是函数的返回值
     5 相当于
     6 def fun1(n):
     7      return n*n
     8 '''
     9 print(cala(10))
    10 
    11 #lambda其它函数先定义好,存入内存。

    七、高阶函数

    高阶函数指的是将函数名作为参数传入。

    1 def high_fun(a,b,f):
    2     return f(a)+f(b)
    3 
    4 >>a = high_fun(1,-2,abs)  #abs()求一个函数的绝对值
    5 3

    上面例子中,参数f可以任意的函数名。

    高阶函数第二种形式,返回值是函数名:

    def fun():
        print("这是一个高阶函数")
        return fun
    a = fun()    #返回的是一个内存对象

    八、常用的内置函数

     1 #zip()函数
     2 a = zip(("a","b","c"),(1,2,3))  #把序列的元素一一配对,每一对为一个元组
     3 b = zip(("a","b","c"),(1,2,3,4)) #多出的部分不会配对
     4 c = zip(("a","b","c","d"),(1,2,3))
     5 d = zip(("a","b","c"),(1,2,3),(1,2,3))  #可以进行多个配对
     6 print(a)        #得到一个zip对象
     7 print(list(a))  #转换为列表的形式
     8 print(list(b))
     9 print(list(c))
    10 #常见的应用,将字典对于的键值提取出来
    11 di = {"name":"wallace","age":18,"gendler":"man"}
    12 print(list(zip(di.keys(),di.values())))
    zip函数
     1 #mix和zip的结合
     2 di = {"alex_age":17,
     3       "wallace_age":18,
     4       "qiangge":20}
     5 
     6 print(max(zip(di.values(),di.keys())))
     7 
     8 #终极用法
     9 
    10 li = [
    11     {"name":"wallace","age":18},
    12     {"name":"budong","age":30},
    13     {"name":"xiaopou","age":32}
    14 ]
    15 
    16 print(max(li,key=lambda x:x["age"]))  #默认参数是一个队li每个元素的处理方法
    max高级用法
     1 #abs()
     2 print(abs(-1))  #取绝对值
     3 #all()
     4 print(all([1,2,3,"1"]))   #对序列内的元素进行bool运算,若全未True则返回True
     5 print(all([1,0,2]))       #若有一为False,则返回False
     6 print(all(""))            #如果可迭代对象是空,返回True
     7 #any()
     8 print(any([1,2,3]))       #与all相反,只要有一个是True就返回True
     9 print(any([1,2,""]))
    10 print(any(""))
    11 #bin()
    12 print(bin(8))             #把一个数的十进制转换为二进制
    13 #hex()
    14 print(hex(17))            #十进制转换为16进制
    15 #oct()
    16 print(hex(8))             #十进制转换为8进制
    17 #bool()
    18 print(bool(""))           #判断bool值,空,None,0为False
    19 #bytes()
    20 print(bytes("你好",encoding="utf-8"))  #将字符转换为二进制格式,必须申明编码方式,即以申明编码转为为二进制
    21 print(bytes("你好",encoding="utf-8").decode("utf-8"))
    22 #decode将二进制解码为,对应的编码格式。注意对应的的编码需要对应的解码,否则容易乱码
    23 #chr()
    24 print(chr(98))            #对应ascii码表的值
    25 #dir()
    26 print(dir(bin))           #打印某一个对象的信息
    27 #divmod()
    28 print(divmod(10,3))       #对第一个参数整除取余操作,得到对应数和余数,常用分页功能
    29 #eval()
    30 dic_str = "{'name':'wallace','age':3}"
    31 print(eval(dic_str))      #将被转化为字符串的Python数据类型转换回对应的的数据类型
    32 print(type(eval(dic_str)))
    33 express = '1+2-1'
    34 print(eval(express))      #也可以将Python的运算转换
    35 #hash() 根据对应的参数得到对应的hash值,无法根据hash值得到原来的值
    36 '''
    37 可hash的数据类型:就是不可变的数据类型
    38 不可hash的数据类型:就是可变的数据类型
    39 同一个值得到的hash值是一样的
    40 作用:可以防止代码被串改
    41 '''
    42 name = "wallace"
    43 print(hash(name))
    44 #id()                     #打印对象的内存地址
    45 print(id(name))
    46 #isinstance()
    47 print(isinstance(1,int))   #判断一个数据是否为某一对象的实例
    48 #max() min()
    49 print(max([1,2,3]))        #取一个序列的最大值
    50 print(min([1,2,3]))        #取最小值
    内置函数
     1 #ord()
     2 print(ord("a"))   #给定字符返回对于ASCII码表的数字
     3 #pow()
     4 print(pow(2,3))   #表示2的3次方
     5 print(pow(2,3,2)) #2的3次方对2取余
     6 #reversed()
     7 print(list(reversed("str")))  #反转序列,得到的是一个reversed对象
     8 #slice()对切片进行赋值,提高代码可读性
     9 li = "wallace"
    10 print(li[1:3])
    11 a = slice(1,3)
    12 print(li[a])
    13 print(a.start)  #获取切片头
    14 print(a.stop)   #获取切片尾
    15 print(a.step)   #获取步长
    16 #sorted()
    17 print(sorted(li))  #排序,同类型才能排序
    18 li = [
    19     {"name":"wallace","age":18},
    20     {"name":"budong","age":30},
    21     {"name":"xiaopou","age":32}
    22 ]
    23 print(sorted(li,key=lambda x:x["age"]))
    24 #str()
    25 print(str([1,3]))   #将别的数据类型转换为字符串形式
    26 print(type(str([2,3])))
    27 #sum()              #去和
    28 print(sum(range(5)))
    内置函数2
     1 from functools import reduce
     2 
     3 li = [1,2,3,4]
     4 
     5 def add_li(x,y):
     6     return x*y
     7 
     8 
     9 def reduce_list(fun,arre,init=None):
    10     if init == None:
    11         res = arre.pop(0)
    12     else:
    13         res = init
    14 
    15     for i in arre:
    16         res = fun(i,res)
    17 
    18     return res
    19 
    20 a = reduce_list(add_li,li)
    21 print(a)
    22 
    23 #reduce就是类似于以上代码实现的功能
    24 #主要就是讲列表或迭代对象的所有元素整合
    25 print(reduce(add_li,li,2))  
    reduce函数
     1 #filter的类似源码
     2 move_sb = ["sb_wallace","sb_allx","sb_ibx","wallace"]
     3 
     4 def fit_head(x):
     5     return x.startswith("sb")
     6 
     7 # def filter_text(fun,res):
     8 #     ies = []
     9 #     for i in res:
    10 #         if not fun(i):
    11 #             ies.append(i)
    12 #     return ies
    13 #
    14 # a = filter_text(fit_head,move_sb)
    15 # print(a)   
    16 
    17 
    18 print(list(filter(fit_head,move_sb)))  
    19 '''
    20 filter函数
    21 第一个参数传入可迭代对象处理的方法
    22 第二个参数传入可迭代对象
    23 '''
    filter
    1 def fun(x):
    2     return x+1
    3 li = (1,2,3)     #li是一个可迭代对象如元祖,列表,字符串等
    4 b=map(fun,i)    #fun就是处理对象的的方法  fun可以用 lambda x: x+1代替
    5 print(b)        #<map object at 0x000000000219FFD0>  返回一个可迭代对象
    6 for i in b:
    7     print(b)
    map函数
  • 相关阅读:
    Java堆栈详解
    JVM 图形化监控工具
    Tomcat 7优化前及优化后的性能对比
    Java 枚举常见7种用法
    GitHub上如何删除repository仓库
    eclipse下使用git上传(下载)代码至(从)github
    标准的软件工程过程之文档标准
    maven添加本地非repository中的jar包
    Junit初级篇
    mongodb拷贝数据库copyDatabase()。实现释放磁盘空间的方法。
  • 原文地址:https://www.cnblogs.com/tashanzhishi/p/8850328.html
Copyright © 2011-2022 走看看