zoukankan      html  css  js  c++  java
  • python学习笔记-函数,递归和内置函数

    函数和过程

    过程:就是没有返回值的函数

    python中过程也是函数,就算没有返回值,也要返回个None

    例子:

    def test(x):
        y=x+1
        return y
    print(test)   #这是打印函数在内存中的地址
    
    
    def test1():
        pass
    
    def test2():
        return 0
    
    def test3(x):
        msg="hello"
        print(msg,x)
        return 1,2,3,'a',["steven","bob"],None
    
    t1=test1()
    t2=test2()
    t3=test3("jobs")
    print(t1)  #None
    print(t2)  #0
    print(t3)  #打印返回的值,是一个元组:(1, 2, 3, 'a', ['steven', 'bob'], None)

    总结:

       返回值数=0:返回None

       返回值数=1:返回object

       返回值数>1:返回tuple

    参数与可变长参数

    过量的参数

    在运行时知道一个函数有什么参数,通常是不可能的。另一个情况是一个函数能操作很多对象。更有甚者,调用自身的函数变成一种api提供给可用的应用。

    对于这些情况,python提供了两种特别的方法来定义函数的参数,允许函数接受过量的参数,不用显式声明参数。这些“额外”的参数下一步再解释。

    注意args和kwargs只是python的约定。任何函数参数,你可以自己喜欢的方式命名,但是最好和python标准的惯用法一致,以便你的代码,其他的程序员也能轻松读懂。

    位置参数

    在参数名之前使用一个星号,就是让函数接受任意多的位置参数。

    def multiply(*args):
        total = 1
        for arg in args:
            total *= arg
        return total
    
    print(multiply(2, 3))
    print(multiply(2, 3, 4, 5, 6))

    python把参数收集到一个元组中,作为变量args。显式声明的参数之外如果没有位置参数,这个参数就作为一个空元组

    关键字参数

    python在参数名之前使用2个星号来支持任意多的关键字参数。

    def accept(**kwargs):
        for keyword, value in kwargs.items():
            print("%s => %r" % (keyword, value))
    
    accept(foo='bar', spam='eggs')

    注意:kwargs是一个正常的python字典类型,包含参数名和值。如果没有更多的关键字参数,kwargs就是一个空字典。

    混合参数类型

    任意的位置参数和关键字参数可以和其他标准的参数声明一起使用。混合使用时要加些小心,因为python中他们的次序是重要的。参数归为4类,不是所有的类别都需要。他们必须按下面的次序定义,不用的可以跳过。

    1)必须的参数
    2)可选的参数
    3)过量的位置参数
    4)过量的关键字参数

    练习:

    #例1
    def add(x,y,z=5):
        res=x+y+z
        print(res)
    
    add(1,z=2,y=9)       #位置参数必须在关键字参数的左边
    
    #例2
    def test(x,*args):
        #print(x)
        print(args)
    
    test(3,[4,5,6,7])    #结果为:([4, 5, 6, 7],)
    test(3,*[4,5,6,7])   #结果为:(4, 5, 6, 7),和test(3,4,5,6,7)一样
    test(3)              #结果为()
    
    #例3
    def test(x,**kwargs):
        #print(x)
        print(kwargs)
    
    test(1,a=3,b=4,c=5)  #{'a': 3, 'b': 4, 'c': 5}
    #test(1,a=3,b=4,c=5,c=5) #报错,一个参数不能传两个值
    
    #例4
    def test(x,*args,**kwargs):
        #print(x)
        print(args)
        print(kwargs)
    
    test(1,10,11,12,13,a=30,b=40,c=50)
    test(1,*[10,11,12,13],**{"a":30,"b":40,"c":50})
    '''结果为:
    (10, 11, 12, 13)
    {'a': 30, 'b': 40, 'c': 50}
    (10, 11, 12, 13)
    {'a': 30, 'b': 40, 'c': 50}
    '''

    局部变量与全局变量

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

    全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
    当全局变量与局部变量同名时:
    在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。
    name='steven'
    def change_name():
        print('名字',name)
    
    change_name() #名字 steven
    
    
    def change_name():
        name='帅哥一枚'
        print('名字',name)
    
    change_name()
    print(name) #steven
    
    
    def change_name():
        global name          #操作的是全局变量
        name='帅哥一枚'
        print('名字',name)
    
    change_name()
    print(name) #帅哥一枚

    补充:

    NAME=["jobs","steven"]
    
    def test():
        NAME.append("mark")
        print("我的朋友有:",NAME)
    
    test()

    总结:如果函数的内部无global关键字,优先读取局部变量;

              可读取全局变量,无法对全局变量重新赋值,但是对于可变类型,可以对全局变量的内部元素进行操作

    如果函数中有global关键字,变量本质上就是全局的那个变量,可读取可赋值

    #1、无global关键字
    #---有声明局部变量
    NAME=["jobs","steven"]
    def test():
        NAME=["zhou"]
        NAME.append("mark")
        print("我的朋友有:",NAME)
    test() #['zhou', 'mark']
    #--未声明局部变量
    NAME=["jobs","steven"]
    def test():
        NAME.append("mark")
        print("我的朋友有:",NAME)
    test() #['jobs', 'steven', 'mark']
    #2、有global关键字
    #---有声明局部变量
    NAME=["jobs","steven"]
    def test():
        global NAME
        NAME = ["zhou"]
        NAME.append("mark")
        print("我的朋友有:",NAME)
    test()#['zhou', 'mark']
    #--错误的例子
    # NAME=["jobs","steven"]
    # def test():
    #     NAME = ["zhou"]
    #     global NAME
    #     NAME.append("mark")
    #     print("我的朋友有:",NAME)
    # test()#报错,局部变量在全局变量声明之前报错,不知道找哪个
    #规范:全局变量变量名全部大写,局部变量变量名小写
    #--未声明局部变量
    NAME=["jobs","steven"]
    def test():
        global NAME
        NAME.append("mark")
        print("我的朋友有:",NAME)
    test()#['jobs', 'steven', 'mark']
    View Code

    函数嵌套与作用域

    #1、
    def test1():
        print("in the test1")
    def test():
        print("in the test")
        return test1
    
    res=test()
    print(res)
    
    #2、
    name="jobs"
    def foo():
        name="mark"
        def bar():
            #name="steven"
            print(name)
        return bar
    a=foo()
    print(a)
    a()   #bar()
    #定义是一部分,执行是一部分。虽然在最外面执行的bar().但是输出结果还是“mark”不论在那个位置调用函数。函数的作用域跟声明的时候有关。
    
    #3、
    def foo():
        name="steven"
        def bar():
            name="mark"
            def tt():
                print(name)
            return tt
        return bar
    
    bar=foo()
    tt=bar()
    print(tt)
    tt()   #mark
    foo()()() #mark

    函数递归

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

    def calc(n):
        print(n)
        if int(n/2) == 0:
            return n
        res=calc(int(n/2))
        return res
    
    r=calc(10)
    print(r)

    例子:问路

    import time
    person_list=["zhou","steven","jobs","mark","sandy"]
    def ask_way(person_list):
        print("-"*60)
        if len(person_list)==0:
            return "根本没人知道"
        person=person_list.pop(0)
        if person=="sandy":
            return "%s说:我知道,就在来福士,下地铁就是"%person
    
        print("Hi,美男[%s]:敢问路在何方" %person)
        print("%s回答说:我不知道,我帮你问问%s"%(person,person_list))
        time.sleep(1)
        res=ask_way(person_list)
        print("%s问的结果是:%s"%(person,res))
    
        return res
    res=ask_way(person_list)
    print(res)

    结果为:

    ------------------------------------------------------------
    Hi,美男[zhou]:敢问路在何方
    zhou回答说:我不知道,我帮你问问['steven', 'jobs', 'mark', 'sandy']
    ------------------------------------------------------------
    Hi,美男[steven]:敢问路在何方
    steven回答说:我不知道,我帮你问问['jobs', 'mark', 'sandy']
    ------------------------------------------------------------
    Hi,美男[jobs]:敢问路在何方
    jobs回答说:我不知道,我帮你问问['mark', 'sandy']
    ------------------------------------------------------------
    Hi,美男[mark]:敢问路在何方
    mark回答说:我不知道,我帮你问问['sandy']
    ------------------------------------------------------------
    mark问的结果是:sandy说:我知道,就在来福士,下地铁就是
    jobs问的结果是:sandy说:我知道,就在来福士,下地铁就是
    steven问的结果是:sandy说:我知道,就在来福士,下地铁就是
    zhou问的结果是:sandy说:我知道,就在来福士,下地铁就是
    sandy说:我知道,就在来福士,下地铁就是
    View Code

    递归特性

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

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

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

    匿名函数

    匿名函数就是不需要显式的指定函数

    def calc(x):
        return x+1
    print(calc(10))
    #换成匿名函数
    func=lambda x:x+1
    print(func(10))
    
    #print(lambda x:x+1) #输出函数地址
    
    test=lambda x,y,z:(x+1,y+1,z+1) #返回多个值时当做元组处理。lambda用法时要手动加括号
    print(test(1,2,3))#(2, 3, 4)

    匿名函数主要是和其它函数搭配使用的

    函数式编程

    编程的三种方法论:

    面向过程

    函数式

    面向对象

    函数式编程可读性查,精简

    特性:

    1、不可变,不用变量保存状态,不修改变量

    #非函数式
    a=1
    def incr_test1():
        global a
        a+=1
        return a
    print(incr_test1())
    #函数式
    n=1
    def incr_test2(n):
        return n+1
    print(incr_test2(2))
    print(n)

    2、第一类对象:函数即变量

    函数名可以当做参数传递

    返回值可以是函数名

    高阶函数:

    满足下面一种情形的就是高阶函数(1、函数接收的参数是一个函数名;2、返回值中包含函数)

    # 把函数当做参数传给另一个函数
    def foo(n):
        print(n)
    
    def bar(name):
        print("my name is %s" % name)
    
    #foo(bar)
    foo(bar("steven"))
    
    
    # 返回值中包含函数
    def bar():
        print("from bar")
    
    def foo():
        print("from foo")
        return bar
    n = foo()
    n()
    
    #返回自己
    def handle():
        print("from handle")
        return handle
    n = handle()
    n()

    尾递归调用优化:

    在函数的最后一步调用另外一个函数(最后一行不一定是函数的最后一步)

    # 非尾调用
    
    def bar(n):
        return n
    def foo(x):
        return bar(x) + 1
    #尾调用
    
    def test1():
        print("from test1")
    
    def test2():
        print("from test2")
        return test1()

    map函数

    num_1=[1,2,10,4,3,7]
    def map_test(func,array):   #func=lambda x=x+1 arrary=[1,2,10,4,3,7]
        ret=[]
        for i in array:
            res=func(i)  #
            ret.append(res)
        return ret
    print(map_test(lambda x:x+1,num_1))
    
    #使用map函数
    res=map(lambda x:x+1,num_1)  #获得的是个可迭代对象,在python2获得的就是个列表
    print(res)          #<map object at 0x0000021E578A0C18>
    print(list(res))    #[2, 3, 11, 5, 4, 8]
    
    msg="ajfaljfiejalf"
    print(list(map(lambda x:x.upper(),msg)))#['A', 'J', 'F', 'A', 'L', 'J', 'F', 'I', 'E', 'J', 'A', 'L', 'F']

    filter函数

    gentleman=["alex_ss","jobs_ss","steven","mark_ss"]
    
    print(filter(lambda n:not n.endswith("ss"),gentleman))#<filter object at 0x000002B2A39D0C18>
    res=filter(lambda n:not n.endswith("ss"),gentleman)
    print(list(res))                         #['steven']

    reduce函数

    num_1=[1,2,3,100]
    def reduce_test(func,array,init=None):
        if init is None:
            res=array.pop(0)
        else:
            res=init
        for num in array:
            res=func(res,num)
        return res
    
    print(reduce_test(lambda x,y:x*y,num_1,10))   #6000
    
    #reduce 用法
    from functools import reduce
    print(reduce(lambda x,y:x*y,num_1,10))       #6000

    总结:

    map函数对一个列表进行特定处理,结果得出一个长度和顺序不变的列表,filter是对一个列表处理筛选一遍得出一个列表出来,reduce把一个完整的序列压缩处理成一个值
    map处理序列中的每个元素,得到的结果是一个"列表",该列表元素个数与位置与原来一样
    filter遍历序列找那个的每个元素,判断每个元素得到布尔值,如果是true则留下来
    reduce处理一个序列,然后把序列进行合并操作

    内置函数

    print(abs(-2))
    print(all([1,2,'1']))
    print(all([1,2,'1',''])) #可迭代对象的每个值是true,返回true
    print(all('')) #true
    print(all([])) #可迭代对象是空,返回true
    print(all([0,'']))#false
    print(all([0,'',1]))#false
    print(bin(3))  #转化成二进制,结果:0b11 0b表示二进制
    print(bool(None)) #空,None,0的布尔值为false,其余都为true
    name='你好'
    print(bytes(name,encoding='utf-8'))
    print(bytes(name,encoding='utf-8').decode('utf-8'))  #decode():python3默认用uft-8解码
    print(bytes(name,encoding='gbk'))
    print(bytes(name,encoding='gbk').decode('gbk'))
    #print(bytes(name,encoding='ascii'))   #错误:ascii不能编码中文
    print(chr(109)) #按照ascii码表对应的顺序输出值
    print(dir(all)) #输出all下面的所有方法名
    print(divmod(10,3)) #结果:(3, 1),得出商和余数
    dict_str='{"name":"steven"}'
    print(eval(dict_str)) #把字符串中的数据结构提取出来
    express="1+2*5-3"
    print(eval(express)) #把字符串中的表达式进行运算
    
    #可hash的数据类型即不可变数据类型,不可hash的数据类型即可变数据类型
    print(hash("9238121hkjk jkjijojo0"))
    help(all)
    
    print(hex(12)) #十进制--》16进制
    print(oct(12)) #十进制--》8进制
    
    print(isinstance(1,int))   #true
    print(isinstance([],list))
    print(isinstance("abc",str))
    
    print(globals())#打印全局变量
    print(locals())#打印局部变量

    max()

    1、max函数处理的是可迭代对象,相当于一个for循环取出每个元素进行比较,注意,不同类型之间不能进行比较
    2、每个元素件进行比较,是从每个元素的第一个位置依次比较,如果这一个位置分出大小,后面的都不需要比较了,直接得出这个元素。

    例子:max与zip方法

    #max场景1
    l=[1,3,100,-3,9]
    print(max(l))
    print(min(l))
    
    print(list(zip(('a','b','c'),(1,2,3))))  #zip创建一个拉链的对象,左右对齐。结果:[('a', 1), ('b', 2), ('c', 3)]
    print(list(zip(('a','b','c'),(1,2,3,4))))#[('a', 1), ('b', 2), ('c', 3)]
    print(list(zip(('a','b','c','d'),(1,2,3))))#[('a', 1), ('b', 2), ('c', 3)]
    #
    p={'name':'steven','age':18,'gender':'none'}
    print(list(zip(p.keys(),p.values()))) #[('name', 'steven'), ('age', 18), ('gender', 'none')]
    print(list(p.keys()))#['name', 'age', 'gender']
    print(list(p.values()))#['steven', 18, 'none']
    print(list(zip('hello','12345'))) #zip里传的两个参数是序列类型(列表,字符串,元祖)
    
    #max场景2
    age_dic={"age1":18,"age2":20,"age3":100}
    print(max(age_dic.values()))#比较的是value,但不知道是哪个key对应的
    print(max(age_dic)) #默认比较字典的key
    
    #max场景3,结合zip
    print(list(max(zip(age_dic.values(),age_dic.keys()))))
    l=["a10","b12","c10"]
    print(list(max(l))) #['c', '1', '0']
    
    #如果l=["a10","b12","c10",100].报错,整形和字符串不能比较,只能相同类型进行比较
    
    
    #max场景4
    people=[{"name":"alex","age":1000},{"name":"steven","age":800},{"name":"mark","age":100}]
    a=max(people,key=lambda dic:dic["age"])
    print(a) #{'name': 'alex', 'age': 1000}

    其他内置函数

    #ord()
    print(ord("a")) #跟chr对应
    
    #pow()
    print(pow(3,3)) #3**3
    print(pow(3,3,2)) #3**3%2
    
    #reversed() 反转
    l=[1,2,3,4]
    print(l)
    print(list(reversed(l)))#[4, 3, 2, 1]
    
    #round() 四舍五入
    print(round(3.6))
    
    #set() 集合
    print(set("hello"))#{'h', 'o', 'e', 'l'}
    
    #slice()
    #场景1,不使用时,可读性差
    l="hello"
    print(l[3:5])
    #场景2.
    l="hello"
    s1=slice(3,5)
    s2=slice(1,4,2)
    print(l[s1])#lo
    print(l[s2])#el
    print(s2.start) #输出切片的开始,1
    print(s2.stop)  #输出切片的结束,4
    print(s2.step)  #输出切片的步长,2
    
    
    #sorted()
    l=[3,2,1,5,7]
    l1=[3,2,"a",1,5,7]
    print(sorted(l))   #[1, 2, 3, 5, 7]
    #print(sorted(l1)) #排序本质就是比较大小,不同类型之间不可以比较大小
    people=[{"name":"alex","age":1000},{"name":"steven","age":800},{"name":"mark","age":100}]
    print(sorted(people,key=lambda dic:dic["age"]))
    #结果为:[{'name': 'mark', 'age': 100}, {'name': 'steven', 'age': 800}, {'name': 'alex', 'age': 1000}]
    
    name_dic={"mark":800,"steven":200,"jobs":500}
    print(sorted(name_dic)) #结果是按照key排序  ['jobs', 'mark', 'steven']
    print(sorted(name_dic,key=lambda key:name_dic[key]))#['steven', 'jobs', 'mark']
    print(sorted(zip(name_dic.values(),name_dic.keys())))#[(200, 'steven'), (500, 'jobs'), (800, 'mark')]
    
    
    #str()转化成字符串
    print(str({"a":1}))
    dic_str=str({"a":1})
    print(eval(dic_str)) #字符串中数据类型提取出来
    
    #sum()
    l=[1,2,3,4]
    print(sum(l))
    print(sum(range(5)))
    
    #type()
    msg='123'
    if type(msg) is str:
        msg=int(msg)
        res=msg+1
        print(res)
    
    #vars() 跟一个列表对象,返回一个字典:不带参数,相当于locals(),打印局部变量的字典形式。有参数,相当于object.__dict__,查看对象下对所有方法的字典形式,没什么用
    def test():
        msg='djfaiefjaleji'
        print(locals())#{'msg': 'djfaiefjaleji'}
        print(vars())#{'msg': 'djfaiefjaleji'}
    test()
    print(vars(int))
    
    #import 不能导入字符串   运行时import实际上调用操作系统,操作系统会找到__import__()方法去导入:import--->sys--->__import__()
    #__import__ 导入字符串的模块名
    import os
    module_name='elementtreexml'
    m=__import__(module_name)
    xmlFilePath = os.path.abspath("movie.xml")
    root=m.readXml(xmlFilePath)
    m.traverseXml(root)
  • 相关阅读:
    Python while循环实现重试
    VBA find查找行号和列号的方法
    通过selenium控制浏览器滚动条
    【转】自然语言处理P,R,F值的计算公式
    【转】ultraedit 正则表达式
    【转】java文件输出流,写到.txt文件,如何实现换行
    Java heap space 解决方法
    XML+RDF——实现Web数据基于语义的描述(转载)
    java学习笔记——jsp简单方法读取txt文本数据
    一个完全独立的今天
  • 原文地址:https://www.cnblogs.com/steven223-z/p/12430129.html
Copyright © 2011-2022 走看看