Python基础学习(二)

发布时间:2019-05-08 22:15:18编辑:auto阅读(1923)

    Python函数总结

    一、函数的基本用法

    1、概念:

    函数是对程序逻辑进行结构化或是过程化的一种编程方法,其是组织好的,可重复使用的,用来实现单一,或者相同功能的代码段。

    函数提高了应用点的模块性和代码的重复利用率

    本质:函数是对功能的封装

    形式参数:简称形参,本质是一个没有值的变量 实际参数:简称实参,本质是常量,变量或者表达式 传参:实参给形参赋值的过程

    而实参的类型取决于形参的需要

    2、函数定义:
      def  函数名(参数1,参数2,参数3.。。。):
    函数体
    return 返回值

    注:a、函数命名遵循标识符规则,做到见名知意,小驼峰命名法、

    b、参数1,参数2,参数3.....形式参数,不同的参数之间使用逗号隔开,参数的数量没有限制,依据具体的需求决定参数的数量

    c、函数体:被封装的功能

    d、return:结束函数,将返回值返回给调用者,也可单独使用

    e、返回值可为常量、变量、表达式

    3、返回值

    返回值:表示一个函数执行完毕之后得到的结果

    注:对于return语句不带参数,则返回一个None

    4、调用

    函数的调用:实质就是函数入栈出栈的过程

    即:函数的入栈:函数被调用;函数的出栈:函数被调用完毕

    注:在函数调用的过程要注意避免出现死循环

    5、变量的作用域

    变量的作用域:指变量可以被访问的范围

    作用域的划分:

    L:(local)局部作用域

    E:(Enclosing)函数作用域(闭包)

    G:(Global)全局作用域

    B:(Built-in)内置作用域

    变量的查找规则(变量重名):

    python中变量的作用域由大到小,依次为内建(built_in B) >全局(glbal G)> 函数的闭包外(enclosing E)> 局部(local L)

    注:在变量重名情况下在函数内部访问变量时使用就近原则。

    如果将全局变量的名字声明在一个函数体内的时候,全局变量的名字能被局部变量给覆盖掉,此时我们就需要使用global或者nonlocal来声明变量了。

      #1.变量不重名
    num1 = 10    #全局作用域

    def outer():
    num2 = 20    #函数作用域
    def inner():
        num3 = 30  #局部作用域
      print(num1,num2,num3)
    return inner

    f = outer()
    f()
      # global:全局的
    # 全局变量
    num1 = 4
    def func1():
      # 声明num1是全局变量的num1
      global  num1
      print(num1)   #4

    num1 = 20
    func1()

    a = 10
    def test():
    global  a
    a = a + 1
    print(a)   #UnboundLocalError: local variable 'a' referenced before assignment
       
    test()


    # nonlocal:不是局部的
    # nonlocal;前提条件:必须使用在闭包中
    x = 0  # 全局作用域
    def outer():
      x = 1       # 函数作用域
       def inner():
          # 将一个局部作用域的变量声明为不是局部的,局部----》函数
        nonlocal x
        x = 2   #局部作用域
        print("inner:",x)
           
    #在外部函数中调用内部函数
    nner()
    print("outer:",x)
    outer()
    print("global:",x)

     

    6、参数

    1、参数的传递:

    参数的传递有值传递和引用传递

    值传递:传递不可变类型的数据,例:num、string、tuple等;在值传递时,形参的改变并不会影响实参

    引用传递:传递可变类型的数据,例:list、dict、set等;形参的改变会影响实参的使用

    在函数中参数传递的是对象的引用

      #引用传递:传递列表或者字典时,如果改变引用的值,就修改了原始的对象
    def check(l):
    print(l)
    print(id(l))
    l.append([1, 23, 2, 3, 4])
    return l
       
    l = [1, 2, 3, 4]
    print(check(l))
    print(id(l))

    '''
    [1, 2, 3, 4]
    2902500909320
    [1, 2, 3, 4, [1, 23, 2, 3, 4]]
    2902500909320
    '''
    #值传递:当传递不可变对象时,如果改变引用变量的值,只是创建了不同的对象,原始对象并没有改变。

    def check(s):
    print(s)
    print(id(s))
    s = "i am test"
    print(id(s))
    return s

    s = "This is a test"
    print(check(s))
    print(s)

    '''
    This is a test
    2418424029424
    2418424029488
    i am test
    This is a test

    2、参数的类型:

    a、必须参数:必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

      def printme( str ):
      "打印任何传入的字符串"
      print str
    return

    #调用printme函数
    printme()

    b、关键字参数:允许实参的顺序和形参的顺序不一致,因为Python解释器会根据关键字参数的名称自动的匹配

      def show2(name,age):
    print("name:%s age:%d" % (name,age))

    show2(name="jack",age=47)
    # 注:关键字参数使用在实参列表中,不要求顺序保持一致
    show2(age=36,name="fadj")
    # 注:在实参列表中,可以不全部设置为关键字参数
    show2("zhangsan",age=15)

    # 注:关键字参数只能出现在实参列表的后面
    def show3(a,b,c):
    print(a,b,c)

    show3(1,4,4)
    show3(a=3,c=5,b=5)
    show3(45,b=9,c=18)
    #show3(a=45,9,18) #SyntaxError: positional argument follows keyword argument

    c、默认参数:调用函数的时候,如果没有传递参数,则使用默认值【default】

      #注意1:默认参数体现在形参列表中
    def func3(name="abc",age=18):
    print("name:%s age:%d" % (name, age))
    #注意2:使用了默认参数,则可以选择不传参,使用的默认值,如果传参,则相当于给形参重新赋值
    func3()
    func3("jack",19)
    #注意3:关键字参数和默认参数可以结合使用
    func3(name="jack",age=19)
    func3("jack",age=19)

    #注意4:形参列表可以不全部设置为默认参数,只要吃部分设置,则默认参数出现在形参列表的后面
    #报错:SyntaxError: non-default argument follows default argument
    # def show4(name="abc",age):
    #     print("name:%s age:%d" % (name, age))
    # show4("bob",18)

    print("hello")

    d、不定长参数:可以处理比声明时更多的参数

      #a.*,一般写法为*args
    def text1(*num):
    print(num)
    for n in num:
        print(n)
           
    # *不定长参数被当做元组处理,num形参名其实就是元组名
    text1(10)
    text1(10,4,54,65,65,7)
    # 可以传一个元组,但是,元组被当做一个整体全部传参
    text1((54,4,64))

    # 一般情况下,将不定长参数设置在形参列表的最后
    def text2(*num3,num1,num2):
    print(num1,num2,num3)

    # 如果不定长参数出现在形参列表的前面或者中间,则可以借助于关键字参数传参
    #text2(12,43,43)
    text2(12,34,num1=35,num2=59)

    # 在形参列表,不定长参数最好只出现一个
    #错误演示
    # def text3(*num3,num2,*num1):
    #     print(num1,num2,num3)
    # text3(43,53,num2=10,5,5,4)


    #b.**,一般写法为**kwargs
    def text4(**num3):
    print(num3)

    #注意1:**,被当做字典处理,传参的时候,需要以key=value的方式进行传参
    text4(x=26,y=17)

    #注意2:在形参列表中使用**,保证出现在后面

    """
    使用场景:单例设计模式
    def text(*args,**kwargs):

    总结:
    a.必需参数使用最多,其次是不定长参数
    b.关键字参数和默认参数最多使用在系统函数中
    """
    7、匿名函数

    lambda表达式:python中的匿名函数主要用来处理一些简单逻辑表达式的封装,使用lambda关键字

    优点:不占用内存,提高代码的运行速度

    一般格式为:

    var = lambda args:表达式
    

    例如:

    f = lambda x,y:x+y
    #该函数的调用结果为 冒号后的表达式所表达的结果
    print(f(1,2))
    

    二、函数进阶

    1、概念【特殊用法】:

    1、变量可以指向函数

    x = abs(-35)
    print(x)   # 35
    
    # 一个普通的变量可以指向一个函数,该变量就可以被当做函数调用
    f = abs
    print(f)
    print(f(-100))
    
    def check():
     	print("check")
    
    check()
    f1 = check
    f1()
    

    2、函数也可以作为变量名

    # 本质:函数名就是一个指向函数的变量
    print(abs(-28))
    # abs = "hello"
    # print(abs(-7))
    

    3、函数作为参数使用

    # 调用形参中的函数,必须和原函数保持一致【注意是否需要传递参数】
    def test(a,b,fun):
     	return fun(a) + fun(b)   #abs(43) + abs(-27)
    print(test(43,-27,abs))  #fun = abs
    
    def test1(s1,s2,func):
     	return func(s1) + func(s2)
    print(test1("hello","gajghj",len))
    
    2、闭包:

    在函数内部定义了另一个函数,即存在外部函数和内部函数

    闭包【closure】:在外部函数中定义一个内部函数,并且外部函数的返回值是内部函数的引用。

    # 普通函数
    def show():
        print("1111")
     	return  num1
    
    # 闭包
    def outter():
     	def inner():
         	print("inner")
     	return inner
    
    f = outter()   #f = inner
    f()
    
    # 在闭包设置参数,a和b两个变量被称为自由变量【临时变量】
    # 闭包的优点:在外部函数中定义的变量,在内部函数可以直接访问
    def outer1(a):
     	b = 10
    	def inner1():
         	print(a + b)
    	return inner1
    
    f1 = outer1(23)  #f1 = inner1
    f1()
    
    
    # 内部函数设置参数
    def outer2(a):
     	b = 10
     	def inner2(c):
         	print(a + b + c)
    	return inner2
    
    f2 = outer2(23)
    f2(12)
    

     

    3、装饰器:

    装饰器【Decorator】:使其他函数在不需要做任何代码的变动下,为函数添加功能,装饰器的返回值也是一个函数。

    本质:装饰器的本质就是一个闭包,其作用是将一个函数作为参数,返回另一个函数

    装饰器函数运行在函数定义的时候

    装饰器需要返回一个可执行的对象

    装饰器返回的可执行对象要兼容函数f的参数

    import  time
    #1.简单的装饰器
    def test():
     	print("hello")
    # func就是需要被装饰的函数
    def outer(func):
     	def inner():
         	# 增加新功能
        	print("new~~~~")
         	# 调用原函数
        	func()
     	return  inner
    
    f1 = outer(test)
    f1()
    
    # 练习:书写装饰器,计算test函数执行的时间
    def outer(func):
     	def inner():
         	t1 = time.time()
            func()
    		t2 = time.time()
    		print(t2 - t1)
    	return  inner
    f1 = outer(test)
    f1()
    
    #2.带有参数的装饰器
    def getAge(age):
     	print(age)
    # getAge(10)
    # getAge(-36)
    # 注意:被装饰的函数有参数,inner不一定需要设置参数,只有当需要在inner内部对参数进行操作的时候,则需要同步
    def wrapper1(func):
     	def inner(a):
         #数据的校验
         	if a < 0:
             	a = -a
            func(a)
     	return  inner
    
    f = wrapper1(getAge)
    f(10)
    f(-36)
    
    
    # 使用装饰器语法糖
    # 注意:使用@,必须保证装饰器存在的情况下,才能给函数增加功能
    def wrapper2(func):
     	def inner(a):
         	# 数据的校验
         	if a < 0:
             	a = -a
    		 func(a)
    	return inner
    
    @wrapper2
    def getAge1(age):
     	print(age)
        
    getAge1(-19)
    
    # 参数为不定长参数的装饰器
    # 使用场景:一个装饰器可以同时作用于多个不同函数的情况
    def wrapper3(func):
     	def inner(*args,**kwargs):
         	# 新增的功能
         	print("abc")
         #调用原函数
         	func(*args,**kwargs)
     	return  inner
    
    @wrapper3
    def test(a,b):
         print(a,b)
    
    test(10,20)
    
    @wrapper3
    def test1():
     print("gsjrg")
    
    test1()
    
    # 多个装饰器作用于同一个函数
    def wrapper11(func):
     	def inner(*args,**kwargs):
         	# 新增的功能
         	print("装饰器~~~~11")
         	# 调用原函数
         	func(*args,**kwargs)
     	return  inner
    
    def wrapper22(func):
     	def inner(*args,**kwargs):
         	# 新增的功能
         	print("装饰器~~~~22")
         	# 调用原函数
         	func(*args,**kwargs)
     	return  inner
    
    @wrapper11    # func:check
    @wrapper22      # func:被wrapper11装饰之后的函数
    def check():
     	print("check")
    
    check()
    #总结:多个装饰器作用于同一个函数的时候,从上往下依次执行,但是,原函数只被调用一次
    
    4、偏函数

    通过设定默认参数,可以降低调用的难度,偏函数也可以起到这样的作用

    概念:对函数的参数做一些控制的函数

    注意:偏函数一般不需要自己定义,直接使用【functools模块其中提供了偏函数的使用】

    import  functools
    
    
    print(int("23534"))
    # print(int("abc345"))  #ValueError: invalid literal for int() with base 10: 'abc345'
    
    # 在int中有一个默认参数base,用来指明当前数据的进制
    print(int("110"))
    print(int("110",base=10))
    print(int("1010",base=2))
    print(int("1010",2))
    # 自定义一个函数,设置一个默认参数base,默认值设置为2
    def int2(x,base=2):
     	return int(x,base)
    
    print(int2("1010"))
    print(int2("1010",10))
    
    # 系统的functools模块中提供了偏函数的实现
    # 参数:已经存在的函数名   默认参数
    int3 = functools.partial(int,base=2)
    print(int3("1110"))
    print(int3("1110",base=10))
    
    # 思想:根据一个已经存在的函数,通过修改该函数参数的默认值,生成一个新的函数,被称为偏函数
    

    三、高阶函数

    1、filter():过滤

    """
    filter(function,iterable)  通过一定的条件过滤可迭代对象中的元素
    
    工作原理:把传入的函数依次作用于可迭代对象的每一个元素,根据返回的布尔值【True或者False】决定是否保留元素
    如果返回True,则表示需要保留该元素;如果返回False,则表示需要过滤掉该元素
    """
    # 将列表中的偶数筛选出来
    list1 = [1,2,3,4,5,6,7,8]
    # 自定义【追加】
    newList1 = []
    for num in list1:
     	if num % 2 == 0:
        	 newList1.append(num)
    print(newList1)
    # 自定义【删除】
    newList2 = list1.copy()
    for num in newList2:
      	if num % 2 == 1:
         	newList2.remove(num)
    print(newList2)
    
    #方式三:列表生成式
    newList3 = [num for num in list1 if num % 2 == 0]
    print(newList3)
    
    # filter
    def func(num):
    	# 保留偶数元素
     	if num % 2 == 0:
         	return True
    	# 过滤奇数元素
     	return False
    
    newList4 = list(filter(func,list1))
    print(newList4)
    
    # 将爱好为"无"的数据剔除掉
    data = [['姓名', '爱好', '年龄'],['tom', '无', 10],['jack', '唱歌', 28]]
    def func2(s):
     	if s == "无":
         	return False
    	 return  True
    for line in data:
      	result = list(filter(func2,line))
      	print(result)
    

    2、map():映射

    """
    map(function,Iterable)  会根据的函数对指定的序列做出映射
    function:函数
    iterable:可迭代对象,序列
    工作原理:函数会以序列中的每一个元素作为参数,返回包含函数的功能的新列表
    功能:将传入的函数依次作用于序列中的每一个元素,并把结果作为新的iterable返回
    """
    # 计算列表中各个元素的平方
    list1 = [1,2,3,4,5]
    # 自定义
    newList1 = []
    for num in list1:
     	newList1.append(num ** 2)
    print(newList1)
    
    # 列表生成式
    newList2 = [num ** 2 for num in list1]
    print(newList2)
    
    # 生成器
    newList3 = list((num ** 2 for num in list1))
    print(newList3)
    
    # map[def定义的函数]
    def func(x):
      return  x ** 2
    
    result = map(func,list1)
    print(result)
    print(type(result))
    newList4 = list(result)
    print(newList4)
    
    """
    传给map的函数的要求:
     a.参数只能有一个【默认将可迭代对象的一个元素传递给该函数】
     b.该函数必须有返回值,否则得到的可迭代对象中的元素为None
    """
    #方式五:map[匿名函数]
    newList5 = list(map(lambda x:x ** 2,list1))
    print(newList5)
    
    # 已知有一个整数列表,将转换为字符串列表
    #例如:[2,3,4,5]------>['2','3','4','5']   str()
    list2 = [2,3,4,5]
    newL1 = []
    for num in list2:
     	newL1.append(str(num))
    print(newL1)
    newL2 = [str(num) for num in list2]
    newL3 = list((str(num) for num in list2))
    newL4 = list(map(str,list2))
    print(newL4)
    

    reduce():迭代【累积】

    from functools import reduce
    """
    导入模块:functools
    reduce(function,iterable):函数会对序列中的元素进行累积
    功能:用传给reduce的函数先序列中的第1,2个元素进行操作,
    用得到的结果和第3个元素进行操作,用得到的结果和第4个元素进行操作。。。。
    
    举例:
    f,[a,b,c,d]
    reduce(f,[a,b,c,d])
    工作原理:f(f(f(a,b),c),d),类似于递归
    """
    
    # 计算一个整数列表中元素的和
    # 一:自定义
    list1 = [1,2,3,4,5]
    total = 0
    for num in list1:
     	total += num
    print(total)
    
    # 二:reduce【def定义函数】
    def mySum(x,y):
     return x + y
    result0 = reduce(mySum,list1)
    print(result0)
    """
    mySum(1,2)---->3
    mySum(3,3)---->6
    mySum(6,4)---->10
    mySum(10,5)---->15
    """
    
    # 三:reduce[匿名函数]
    result1 = reduce(lambda x,y:x + y,list1)
    print(result1)
    """
    函数的注意事项:
     a.必须有两个参数
     b.必须设置返回值【报错:TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'】
    """
    
    # 将[1,3,5,7,9]转换为整数13579
    list2 = [1,3,5,7,9]
    def func(x,y):
     	return  x * 10 + y
    
    result3 = reduce(func,list2)
    print(result3)
    
    # 自定义一个函数,实现str转换为int的函数  int(xx)
    def charToNum(s):
     # 自定义字符串和整型之间的映射关系
     	digits = {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6}
      return digits[s]
    
    # 需求:“24356”------》24356
    # a.产生映射关系
    r0 = list(map(charToNum,"24356"))
    print(r0)
    #b.使用reduce累积
    r1 = reduce(func,r0)
    print(r1)
    print(type(r1))
    
    r2 = reduce(func,map(charToNum,"23456"))
    print(r2)
    

     

关键字