Python基础(三)

作者: EvanForEver | 来源:发表于2018-02-08 19:44 被阅读16次

Python中的函数

  1. 函数的意义:
  • 对输入进行变换映射后输出
  • 过程化VS 结构化
  1. 函数的创建及结构:
  • 定义函数名
  • 参数
  • 函数体
  • 返回
     有无返回
    (无返回值即无return或者return后为空。return返回的是对象,如返回对象数>1则返回元组)
     return与yield的区别
    (return:函数执行到return处返回一个对象,函数结束)
    (yield:函数执行到yeild处返回一个生成器,记录函数执行情况,再次调用会接着执行)

函数中的参数

  1. 参数语法:func(positional_args,keyword_args,*tuple_nonkw_args,**dict_kw_args)
  2. 按参数传递方式:
     位置参数(别称:定位参数,非关键字参数) :对位置敏感,传递时不用指定参数名
     关键字参数:不传关键字参数函数可以被调用,采用默认值,传关键字参数,覆盖默认值
     位置参数包裹及使用* (非关键字不定长参数 args*)
     关键字参数包裹及使用**(关键字的不定长参数 kwargs*)
     包裹解包顺序(首先拆位置参数包裹,按顺序给必选,默认,可变、关键字参数包裹)
     传递参数时使用包裹
#位置参数包裹及使用*,一次传入不定长个位置参数
>>def mysum2(*args):
>>    print(type(args))
>>    return sum(args)
>>mysum2(5,7,5,8,9)#正常调用
<class 'tuple'>
34

>>def filmInfo(**kwargs):
>>    print(type(kwargs))
>>    for key,values in kwargs.items():
>>        print(key,':',values)

#关键字参数包裹及使用**,一次性传入不定长关键字参数
>>filmInfo(film='羞羞的铁拳',box=3.5,rate=7.9)
<class 'dict'>
film : 羞羞的铁拳
box : 3.5
rate : 7.9

#传递参数时使用包裹
#传递参数时使用包裹-位置参数
>>l1=[1,5,6,7,2,5,3.5,9,6,3,4]
>>mysum2(*l1)
<class 'tuple'>
51.5

#zip案例
>>l1=[(1,3),(2,4),(5,6)]
>>list(zip(*l1)) #即 list(zip(l1[0],l1[1],l1[2]))
[(1, 2, 5), (3, 4, 6)]

##传递参数时使用包裹-关键字型参数
>>d1={'羞羞的铁拳':3.5,'雷神3':3.1,'战狼2':60}
>>filmInfo(**d1)
<class 'dict'>
羞羞的铁拳 : 3.5
雷神3 : 3.1
战狼2 : 60

  1. 按参数的类型:
     必选(位置参数)
     关键字/默认
     *args可变长位置参数,**kwargs可变长关键字参数
  2. 函数如何处理传入参数:
     值传递参数与指针传递参数
    (值传递时(数值和字符串),变量传递给函数后,函数复制一份,不会影响原有变量)
    (指针(或引用)传递时(列表和字典),传递给函数的是引用,该引用可以改变原变量)

变量作用域

locals()#查看局部变量名称空间
globals()#查看全局变量名称空间

  1. 全局变量
     在模块内、在所有函数外面、在class外面
     供全局共享,全局类和函数均可访问,达到同步作用。使用时,需要用global显示声明
     程序执行时除非被del才会消失
  2. 局部变量
     函数内部创建与访问
     只在函数调用时存在,调用结束后变量不存在
     搜索时:局部作用域->全局作用域

偏函数PFA

  • 偏函数Partial function application:如果一个函数的参数很多,而在每次调用的时候有一些又经常不需要被指定时,就可以使用偏函数(近似理解为默认值)
     语法:partical(func,*args,**keywords)
     使用:from functools import partial
     原理:创建一个新函数,固定住原函数的部分参数(可以为位置参数,或是关键字参数)
>>def hex2int1(x,base=16):
>>    #base为关键字参数,在调用int函数时固定给16。用来转换16进制到10进制
>>    return  int(x,base)
>>hex2int('F')
#相当于:int('F',base=16),这样就少写了一个参数

#functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义
>>import functools
>>max100=functools.partial(max,100)
#定义一个叫max100的偏函数,将这个偏函数的第一个值固定为100
>>max100(101)#这时调用它,传入的值与100进行比较并返回较大的值。
101

递归函数

定义:函数在内部调用自身

#使用递归分解质因数
>>l1=[]
>>def fenji(num):
>>    num=int(num)
>>    for i in range(2,num):
>>            if num%i==0:
>>                l1.append(i)
>>                nextv=int(num/i)
>>                fenji(nextv)
>>                break#这里的break不加就会硬循环60次                
>>    return l1
>>fenji(60)
[2, 2, 3]

#阶乘
>>def factorial(n):
>>    if n==1:
>>        return 1
>>    else:
 >>       return n*factorial(n-1)
>>factorial (5)
120

高阶函数

  • 函数的引用与调用
     引用:同一个对象被多个不同的变量名引用,函数对象的引用可以del删除
     调用:函数名加(),使用函数
     函数对象既然可以被引用,那就可以作为参数被传入或作为结果被返回
  • 高阶函数: 一个函数接收另一个函数作为参数
  • 回调函数: 函数作为调用函数的结果返回
#高阶函数
>>def mycalucate(num,func):
>>    return func(num)

>>l1=[5,8,3,6,9,15,22]

>>mycalucate(l1,max)
>>mycalucate(l1,min)


#回调函数
def callbackfunc(*num):
    return max
callbackfunc(53,5,33)

BIFs中的高阶函数

  1. filter
     语法:filter(function,list)
     使用:function函数对列表的每个元素进行判断,返回True或 False;filter()则根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。
    list(filter(lambda x:True if type(x)==str else False,l1))
  2. map
     语法:map(function, list)
     使用:list的每一个元素依次调用function函数,并获取返回值存入一个新的list中。
    map(lambda x:(x,l1.count(x)),l1)
  3. reduce
     语法:reduce(function, list)
     使用:函数function必须包含两个参数,reduce()对list的每个元素反复调用函数function,并返回最终结果值。
    from functools import reduce ; reduce(lambda a,b:a+b,[1,2,3,4,5,6,7,8])
     Python 3.x中,reduce()函数和partical一样被放置在fucntools模块中。使用前需要调用

匿名函数lambda

  • 语法:lambda(args1,args2, argsN):expression
  • 使用:
     定义后,赋值给一个变量,做正常函数使用
     lambda关键字定义在高阶函数的参数位上
#使用1:作为正常函数使用,不推荐
>>foo=lambda x,y:x+y #不用写return
>>print(foo(5,6))
11

#使用2:lambda关键字定义在高阶函数的参数位上
>>d1={'china':15,'India':9,'USA':2,'Japan':1.5}
# 这里sorted是高阶函数,key接受一个函数,选择排序的参照物
>>sorted(d1.items(),key=lambda x:(x[0],x[1]))
#按d1.items()第0个元素升序,国家名相同按人口数排列 
# sorted(d1.items(),key=lambda x:(x[1]))#按第1个元素人口数升序排列

闭包Closure

  • 定义:涉及嵌套函数时才有闭包问题,内层函数引用了外层函数的变量(参数),然后返回内层函数的情况,称为闭包(Closure)。
     这些外层空间中被引用的变量叫做这个函数的环境变量。
     环境变量和这个非全局函数一起构成了闭包。
  • 闭包的特点:函数会记住外层函数的变量
>>nums_in_global=[15,2,3,9,3.2]#声明一个全局

>>def foo1(nums_in_function):
>>    print('nums_in_function此时在是foo1中,可以被访问:',nums_in_function)
>>    def foo2():
>>        return max(nums_in_function)
           #虽然没有给foo2传入任何参数,但foo2却能访问到foo1中的变量>>nums_in_function
#         return max(nums_in_global)
           #虽然没有给foo2传入任何参数,但foo2却能访问到全局变量nums_in_global
       return foo2
#调用
>>foo1([5,3,8])()
nums_in_function此时在是foo1中,可以被访问: [5, 3, 8]
8
>>foo1([5,3,8])
nums_in_function此时在是foo1中,可以被 访问: [5, 3, 8]
<function __main__.foo1.<locals>.foo2>

装饰器Decorator

 定义:以函数作参数并返回一个替换函数的可执行函数,为已存在的对象添加额外功能,本质上就一个返回函数的高阶函数
 应用:给函数动态增加功能(函数)
 使用:@是python装饰器的简便写法,也叫语法糖,语法糖在要被包裹的函数前声明。

#现有如下 三个函数
def foo1():
    print ('this is foo1 function')

def foo2():
    print ('this is foo2 function')

def foo3():
    print ('this is foo3 function')
    
#现在想为每一个函数都添加一个打印当前时间的功能
#方法一:在每个函数中各添加代码打印时间,过于麻烦
#方法二:写一个函数,负责打印时间,然后在原来的三个函数中调用
#方法三:先写一个函数接收并打印时间,再调用原函数。
def foo1():
    print ('this is foo1 function')

def foo2():
    print ('this is foo2 function')

def foo3():
    print ('this is foo3 function')

def extrafoo(func):
    print(datetime.datetime.now())
    return func

decorated=extrafoo(foo2)
decorated()
#方法四:使用装饰器
import datetime
def extrafoo(func):
    def inner():
        print('extra:',datetime.datetime.now())
        print('from inner to execute:',func.__name__)
        print('the',func.__name__,'result:',func())
    return inner

@extrafoo#装饰器特性,被装饰的函数定义之后立即运行。
>>def foo1():
>>    return 'this is foo1 function--'

>>foo1()
extra: 2018-02-08 19:38:26.047277
from inner to execute: foo1
the foo1 result: this is foo1 function--

相关文章

网友评论

    本文标题:Python基础(三)

    本文链接:https://www.haomeiwen.com/subject/igrazxtx.html