• Python之路-函数


    一.函数是什么

      python中函数定义:函数是逻辑结构化和过程化的一种编程方法。定义函数的方法为:

    def function():
    ""The function definitions""
        do  something
        return reselut
        
    def:定义函数的关键字
    function 函数名
    ()括号内可定义形参或者实参
    ""可描述函数功能,非必选
    结构体:do somethin,完成某种功能
    return:将函数结果返回

    二.使用函数的好处

      1.减少代码重用

      2.保持一致性,易维护。相同功能可以使用同一个函数,功能发生改变时,直接修改函数即可

      3.扩展性更好

    三.函数的参数(实参,形参,可选参数,默认参数)

    1.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量

    2.实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

    def test(a):  #a为形参,在函数结构体中起到占位的作用
        return a*a
    
    test(1)  #1为实参

    3.位置参数和关键字(标准调用:实参与形参位置一一对应;关键字调用:位置无需固定)

    def test(a,b,c,d)
        print(a)
        print(b)
        print(c)
        print(d)
    
    test(1,d=2,c=3,b=1)
    '''
    使用关键字传参,可不用注意参数的位置
    '''

    4.可选参数  *args  **kwargs(如果同时存在,**kwargs位置需要在*args后面)

    *args以元组的形式传递多个参数

    def fun(*args):
        print(args)
        print(type(args))
    fun(1,2,3,4)
    
    结果:
    (1, 2, 3, 4)
    <class 'tuple'>

    **kwargs 以字典的形式传递多个参数,所以参数需要是

    def fun(**kwargs):
        print(kwargs)
        print(type(kwargs))
    fun(a=1,b=2,c=3,d=4)
    
    输出结果:
    {'a': 1, 'b': 2, 'c': 3, 'd': 4}
    <class 'dict'>

    5.默认参数

      设置好默认参数,如果该形参参数无对应的实参,则使用默认参数

    def fun(a='b'):
        print(a)
    
    fun()
    fun('a')
    
    输出结果
    b
    a

    四.局部变量和全局变量 

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

      全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
      当全局变量与局部变量同名时(为防止同名出现问题,全局变量全部用大写,局部变量用小写):
      在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。
      
      在函数中,使用 global 关键字来定义全局变量,我们分情况来看下现象:
      1.没有global关键字,且未定义变量,则使用全局变量。
    name=123
    def fun():
        print(name)
    fun()
    
    输出结果:
    123

      2.没有global关键字,则在函数中重新定义了变量,则函数内使用局部变量,全局变量保存不变

    name=123
    def fun():
        name=234
        print(name)
    fun()
    print(name)
    
    输出结果:
    234
    123

      由此可知,函数没有global关键字时,对全局变量只有读的权限,没有重新赋值的权限。需要注意的是:当全局变量为可变数据类型(列表,字典)时,函数是可以进行列表内容的修改。由此可见得,函数无法为全局变量开辟新的内存空间,但是可以对其内存地址存储内容进行修改。

    name=[1,2,3,4]
    def fun():
        name.append(5)
        print(name)
    fun()
    print(name)
    
    输出结果:
    [1, 2, 3, 4, 5]
    [1, 2, 3, 4, 5]

      3.有global关键字,且重新定义了全局变量。则会修改全局变量。

    name=123
    def fun():
        global name
        name=234
        print(name)
    fun()
    print(name)
    
    输出结果:
    234
    234

      我们要注意,不能在函数内,global前再定义变量,这样global无法区分你要申请的是全局变量还是 局部变量,会导致报错。

    name=234
    def fun():
        name = 123
        global name
        print(name)
    fun()
    
    报错信息:
    SyntaxError: name 'name' is assigned to before global declaration

      4.有global关键字,则定义的变量在全局变量中不存在,则创建全局变量。  

    def fun():
        global name
        name=234
        print(name)
    
    def fun1():
        print('fun1',name)
    
    fun()
    fun1()
    
    输出结果:
    234
    fun1 234

      当我们无论在内嵌多少层的函数中使用global时,他都会变为全局变量。在内存中,可理解为:

      

         global在此告一段落,接下来,介绍一下内嵌函数如何使用上层函数的变量。

       nonlocal 关键字,定义了内嵌函数使用上层函数的变量

    name=234
    def fun():
        name=1
        def fun1():
            nonlocal name
            print('fun1',name)
        fun1()
    fun()
    
    输出结果:
    fun1 1

      如果我们在第一层函数上使用该关键字,则会报错。所以不能在第一层函数使用该关键字。

     
    五.函数即变量
      函数和变量一样,可以将函数的内容或者结果赋值给新的变量名,通过调用变量名来进行调用函数内容。下面,通过一个简单的例子来看知悉函数的过程
    def func():   #定义函数时,将函数内容以字符串形式保存在内存里
        print('test')
        return func
    
    print('haha')  #第一步,执行打印命令
    func()           #调用函数,将内存中存储的字符串当命令使用
    a=func()      #将func的内存地址赋值给变量名a
    a()              #通过a来调用函数func
    
    打印结果:
    haha
    test
    test
    test

      函数调用前,都需要先将函数内容读取到内存中,再进行调用。和变量一样。我们定义变量时,会先将变量名和内容读取到内容中。当我们在调用变量名时,如果内存中午对应的值,则会报错。

    错误示例:
    print(name)
    name='haha'
    
    func()
    def func():
        print('this is func')

      当我们执行函数时,只要函数内容已经存在内存中,则不分它存储的前后顺序。如下示例,虽然在定义函数时,func()调用func1时,func1并未定义,但是执行时func,func1都已经定义好了,故执行未报错。

    def func():
        print('this is func')
        func1()
    
    def func1():
        print('this is func1')
    
    func()
    
    输出结果:
    this is func
    this is func1

    六.递归函数

      递归函数:在函数内部,可以调用其他函数。如果在调用一个函数的过程中直接或间接调用自身本身,则是递归函数。

     1 def calc(n):
     2     print(n)
     3     if int(n/2) ==0:
     4         return n
     5     return calc(int(n/2))
     6  
     7 calc(10)
     8  
     9 输出:
    10 10
    11 5
    12 2
    13 1

    递归特性:

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

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

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

      由于递归函数的效率性不高,所以可以使用尾部调用来进行调优。即在函数的最后一步进行函数调用(最后一步不一定在最后一行)。这样就可以再调用函数完,即可释放内存。

    函数的作用域

      函数变量的作用域取决去它所在的内存位置,而不是在代码中所调用的位置。例如:

    def scope():
        scope_var='this is scope'
        def scope1():
            scope_var='this is scope1'
        scope1()
        print(scope_var)
        return scope1
    
    var=scope()   #scope1
    
    '''
    虽然是在主程序中直接调用了scope1函数,但是scope_var='this is scope1'的作用域还是只在scope函数下的scope1函数中,
    这是因为python在读取函数定义时,已经按照相应层级读取到内存中。在主程序的调用只是直接调用内存而已
    '''

    高阶函数

      满足俩个特性任意一个即为高阶函数

      1.函数的传入参数是一个函数名

      2.函数的返回值是一个函数名

      map函数

      map(func, *iterables) --> map object,处理序列中的每个元素,得到的结果是一个‘列表 ’,该‘列表’元素个数及位置与原来一样。map函数的原理如下:

    def map_test(func,list_name):
        res=[]
        for i in list_name:
            res.append(func(i))
        return res
    
    def add_one(n):
        return n*n
    test=[1,2,3,4,5]
    print(map_test(add_one,test))

       可以用lambda来处理对象 

    print(list(map(lambda x:x+1,[1,2,3,4])))

      filter函数

      filter(function or None, iterable) --> filter object,遍历序列中的每个元素,判断每个元素的布尔值,如果为Ture,则留下该值。filter的原理如下 :

    name=['sb1','sb2','3sb','xb']
    def func(item):
        return not item.startswith('sb')
    
    def filter_test(func,item):
        new_list=[]
        for i in  item:
            if func(i):
                new_list.append(i)
        return new_list
    
    print(filter_test(func,nam

      可以用lambda来处理对象 

    list(filter(lambda x:not x.startswith('sb'),name))

      reduce函数

      reduce(function, sequence[, initial]) -> value,reduce()处理一个序列,然后把序列进行合并操作。原理如下:

    def func(res,i):
        return res+i
    def reduce_test(func,seq,init=None):
        if  init == None:
            res=seq.pop(0)
        else:
            res=init
        for i in seq:
            res=func(res,i)
        return res
    seq=[1,2,3,4,5,6,]
    print(reduce_test(func,seq))

      用lambda来处理对象 

    from functools import reduce
    seq=[1,2,3,4,5,6,]
    print(reduce(lambda  x,y:x+y,seq))

    内置函数

    #abs()
    print(abs(-1)) #去绝对值
    
    #all()
    print(all([1,'',None])) #判断序列元素布尔值是否都为True,有一个为False,则返回False.空列表,空字符串等返回Ture
    print(all(''))  #True
    print(all(['']))  #False
    
    #any
    print(any([1,'',None])) #判断序列元素布尔值是否都为False,有一个为True,则返回True.空列表,空字符串等返回False
    print(any(''))  #False
    print(any([1,'',None]))  #True
    
    #bin
    bin(12) #将十进制转换为二进制
    
    #bool()   判断bool值
    print(bool(0))
    
    #chr  根据序号找到acsii码表对应的字符
    print(chr(97))
    
    #ord  根据字符,找出对应的ascii码对应的序号
    print(ord('a'))
    
    #compile() 将source编译为代码或者AST对象。代码对象能够通过exec语句来执行或者eval()进行求值。 没什么用。忽略
    
    #divmod(x, y) 返回元组(x//y, x%y),即返回商的整数和余数部分
    print(divmod(3,2))
    View Code
    字典的运算:最小值,最大值,排序
    salaries={
        'egon':3000,
        'alex':100000000,
        'wupeiqi':10000,
        'yuanhao':2000
    }
    
    迭代字典,取得是key,因而比较的是key的最大和最小值
    >>> max(salaries)
    'yuanhao'
    >>> min(salaries)
    'alex'
    
    可以取values,来比较
    >>> max(salaries.values())
    100000000
    >>> min(salaries.values())
    2000
    但通常我们都是想取出,工资最高的那个人名,即比较的是salaries的值,得到的是键
    >>> max(salaries,key=lambda k:salary[k])
    'alex'
    >>> min(salaries,key=lambda k:salary[k])
    'yuanhao'
    
    
    
    也可以通过zip的方式实现
    salaries_and_names=zip(salaries.values(),salaries.keys()) 
    
    先比较值,值相同则比较键
    >>> max(salaries_and_names)
    (100000000, 'alex')
    
    
    salaries_and_names是迭代器,因而只能访问一次
    >>> min(salaries_and_names)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: min() arg is an empty sequence
    
    
    
    sorted(iterable,key=None,reverse=False)
    View Code
  • 相关阅读:
    新手第一次联系oracle的碰到的触发器不能创建的问题
    dubbo注册中心占位符无法解析问题(二)
    dubbo注册中心占位符无法解析问题(一)
    .
    Ubuntu16 安装后配置
    TiDB-----使用 TiUP cluster 在单机上模拟生产环境部署步骤
    TiDB 单机安装(在 Linux OS 上部署本地测试环境)
    WPF查找子控件和父控件方法
    Java基础相关
    C++ namespace浅析
  • 原文地址:https://www.cnblogs.com/white-small/p/6854730.html
Copyright © 2020-2023  润新知