Python学习之函数篇,,函数基础定义函数#语


函数基础

定义函数
#语法def 函数名(参数1,参数2,参数3,...):    ‘‘‘注释‘‘‘    函数体    return 返回的值#函数名要能反映其意义
#1、无参:应用场景仅仅只是执行一些操作,比如与用户交互,打印#2、有参:需要根据外部传进来的参数,才能执行相应的逻辑,比如统计长度,求最大值最小值#3、空函数:设计代码结构
技术图片
#定义阶段def tell_tag(tag,n): #有参数    print(tag*n)def tell_msg(): #无参数    print(‘hello world‘)#调用阶段tell_tag(‘*‘,12)tell_msg()tell_tag(‘*‘,12)‘‘‘************hello world************‘‘‘#结论:#1、定义时无参,意味着调用时也无需传入参数#2、定义时有参,意味着调用时则必须传入参数
有参、无参技术图片
def auth(user,password):                                 ‘‘‘                                                               auth function                                                     :param user: 用户名                                                  :param password: 密码                                               :return: 认证结果                                                     ‘‘‘                                                               pass                                                                                                                            def get(filename):                                                    ‘‘‘                                                               :param filename:                                                  :return:                                                          ‘‘‘                                                               pass                                                                                                                            def put(filename):                                                    ‘‘‘                                                               :param filename:                                                  :return:                                                          ‘‘‘    pass       def ls(dirname):                                                      ‘‘‘                                                               :param dirname:                                                   :return:                                                          ‘‘‘                                                               pass#程序的体系结构立见 
空函数调用函数
#函数的调用:函数名加括号#1 先找到名字#2 根据名字调用代码#函数返回值#无return->None#return 1个值->返回1个值#return 逗号分隔多个值->元组#调用函数的三种形式#1 语句形式:foo()#2 表达式形式:3*len(‘hello‘)#3 当中另外一个函数的参数:range(len(‘hello‘))
函数参数技术图片
1、位置参数:按照从左到右的顺序定义的参数        位置形参:必选参数        位置实参:按照位置给形参传值#2、关键字参数:按照key=value的形式定义的实参        无需按照位置为形参传值        注意的问题:                1. 关键字实参必须在位置实参右面                2. 对同一个形参不能重复传值#3、默认参数:形参在定义时就已经为其赋值        可以传值也可以不传值,经常需要变得参数定义成位置形参,变化较小的参数定义成默认参数(形参)        注意的问题:                1. 只在定义时赋值一次                2. 默认参数的定义应该在位置形参右面                3. 默认参数通常应该定义成不可变类型#4、可变长参数:        可变长指的是实参值的个数不固定        而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参对应有两种解决方案来完整地存放它们,分别是*args,**kwargs        ===========*args===========        def foo(x,y,*args):            print(x,y)            print(args)        foo(1,2,3,4,5)        def foo(x,y,*args):            print(x,y)            print(args)        foo(1,2,*[3,4,5])        def foo(x,y,z):            print(x,y,z)        foo(*[1,2,3])        ===========**kwargs===========        def foo(x,y,**kwargs):            print(x,y)            print(kwargs)        foo(1,y=2,a=1,b=2,c=3)        def foo(x,y,**kwargs):            print(x,y)            print(kwargs)        foo(1,y=2,**{‘a‘:1,‘b‘:2,‘c‘:3})        def foo(x,y,z):            print(x,y,z)        foo(**{‘z‘:1,‘x‘:2,‘y‘:3})        ===========*args+**kwargs===========        def foo(x,y):            print(x,y)        def wrapper(*args,**kwargs):            print(‘====>‘)            foo(*args,**kwargs)#5、命名关键字参数:*后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递可以保证,传入的参数中一定包含某些关键字        def foo(x,y,*args,a=1,b,**kwargs):            print(x,y)            print(args)            print(a)            print(b)            print(kwargs)        foo(1,2,3,4,5,b=3,c=4,d=5)        结果:            1            2            (3, 4, 5)            1            3            {‘c‘: 4, ‘d‘: 5}
重点!作用域
#1、作用域即范围        - 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效      - 局部范围(局部名称空间属于该范围):临时存活,局部有效#2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下x=1def f1():    def f2():        print(x)    return f2x=100def f3(func):    x=2    func()x=10000f3(f1())#3、查看作用域:globals(),locals()LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__locals 是函数内的名字空间,包括局部变量和形参enclosing 外部嵌套函数的名字空间(闭包中常见)globals 全局变量,函数定义所在模块的名字空间builtins 内置模块的名字空间
函数嵌套
def f1():    def f2():        def f3():            print(‘from f3‘)        f3()    f2()f1()

闭包函数

什么是闭包
#内部函数包含对外部作用域而非全局作用域的引用        def counter():            n=0            def incr():                nonlocal n                x=n                n+=1                return x            return incr        c=counter()        print(c())        print(c())        print(c())        print(c.__closure__[0].cell_contents) #查看闭包的元素
闭包的意义和作用
#闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域#应用领域:延迟计算(原来我们是传参,现在我们是包起来)    from urllib.request import urlopen    def index(url):        def get():            return urlopen(url).read()        return get    baidu=index(‘http://www.baidu.com‘)    print(baidu().decode(‘utf-8‘))

装饰器

什么是装饰器
#装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。#强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式#装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
技术图片
被装饰函数的正上方,单独一行        @deco1        @deco2        @deco3        def foo():            pass        foo=deco1(deco2(deco3(foo)))
装饰器语法装饰器的使用技术图片
import timedef timmer(func):    def wrapper(*args,**kwargs):        start_time=time.time()        res=func(*args,**kwargs)        stop_time=time.time()        print(‘run time is %s‘ %(stop_time-start_time))        return res    return wrapper@timmerdef foo():    time.sleep(3)    print(‘from foo‘)foo()
无参装饰器技术图片
def auth(driver=‘file‘):    def auth2(func):        def wrapper(*args,**kwargs):            name=input("user: ")            pwd=input("pwd: ")            if driver == ‘file‘:                if name == ‘egon‘ and pwd == ‘123‘:                    print(‘login successful‘)                    res=func(*args,**kwargs)                    return res            elif driver == ‘ldap‘:                print(‘ldap‘)        return wrapper    return auth2@auth(driver=‘file‘)def foo(name):    print(name)foo(‘egon‘)
有参装饰器

迭代器

#迭代是Python最强大的功能之一,是访问集合元素的一种方式。#迭代器是一个可以记住遍历的位置的对象。#迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。#迭代器有两个基本的方法:iter() 和 next()。#字符串,列表或元组对象都可用于创建迭代器
技术图片
#!/usr/bin/python3 list=[1,2,3,4]it = iter(list)    # 创建迭代器对象for x in it:    print (x, end=" ")
示例技术图片
#基于for循环,我们可以完全不再依赖索引去取值了dic={‘a‘:1,‘b‘:2,‘c‘:3}for k in dic:    print(dic[k])#for循环的工作原理#1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic#2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码#3: 重复过程2,直到捕捉到异常StopIteration,结束循环
for循环工作原理技术图片
#优点:  - 提供一种统一的、不依赖于索引的迭代方式  - 惰性计算,节省内存#缺点:  - 无法获取长度(只有在next完毕才知道到底有几个值)  - 一次性的,只能往后走,不能往前退
迭代器的优缺点

生成器

#在 Python 中,使用了 yield 的函数被称为生成器(generator)。#跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。#在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。#调用一个生成器函数,返回的是一个迭代器对象。
技术图片
#!/usr/bin/python3 import sys def fibonacci(n): # 生成器函数 - 斐波那契    a, b, counter = 0, 1, 0    while True:        if (counter > n):             return        yield a        a, b = b, a + b        counter += 1f = fibonacci(10) # f 是一个迭代器,由生成器返回生成 while True:    try:        print (next(f), end=" ")    except StopIteration:        sys.exit()
示例

表达式

技术图片
name=input(‘姓名>>: ‘)res=‘SB‘ if name == ‘alex‘ else ‘NB‘print(res)
三元表达式技术图片
#1、示例egg_list=[]for i in range(10):    egg_list.append(‘鸡蛋%s‘ %i)egg_list=[‘鸡蛋%s‘ %i for i in range(10)]#2、语法[expression for item1 in iterable1 if condition1for item2 in iterable2 if condition2...for itemN in iterableN if conditionN]类似于res=[]for item1 in iterable1:    if condition1:        for item2 in iterable2:            if condition2                ...                for itemN in iterableN:                    if conditionN:                        res.append(expression)#3、优点:方便,改变了编程习惯,可称之为声明式编程
列表推导式技术图片
#1、把列表推导式的[]换成()就是生成器表达式#2、示例:生一筐鸡蛋变成给你一只老母鸡,用的时候就下蛋,这也是生成器的特性>>> chicken=(‘鸡蛋%s‘ %i for i in range(5))>>> chicken<generator object <genexpr> at 0x10143f200>>>> next(chicken)‘鸡蛋0‘>>> list(chicken) #因chicken可迭代,因而可以转成列表[‘鸡蛋1‘, ‘鸡蛋2‘, ‘鸡蛋3‘, ‘鸡蛋4‘,]#3、优点:省内存,一次只产生一个值在内存中
生成器表达式

递归

#递归调用是函数嵌套调用的一种特殊形式,函数在调用时,直接或间接调用了自身,就是递归调用
技术图片
#直接调用本身def f1():    print(‘from f1‘)    f1()f1()#间接调用本身def f1():    print(‘from f1‘)    f2()def f2():    print(‘from f2‘)    f1()f1()# 调用函数会产生局部的名称空间,占用内存,因为上述这种调用会无需调用本身,python解释器的内存管理机制为了防止其无限制占用内存,对函数的递归调用做了最大的层级限制四 可以修改递归最大深度import syssys.getrecursionlimit()sys.setrecursionlimit(2000)def f1(n):    print(‘from f1‘,n)    f1(n+1)f1(1)虽然可以设置,但是因为不是尾递归,仍然要保存栈,内存大小一定,不可能无限递归,而且无限制地递归调用本身是毫无意义的,递归应该分为两个明确的阶段,回溯与递推
示例

匿名函数

匿名就是没有名字def func(x,y,z=1):    return x+y+z匿名lambda x,y,z=1:x+y+z #与函数有相同的作用域,但是匿名意味着引用计数为0,使用一次就释放,除非让其有名字func=lambda x,y,z=1:x+y+z func(1,2,3)#让其有名字就没有意义

内置函数

技术图片

Python学习之函数篇

评论关闭