函数(匿名函数,嵌套函数,高阶函数,装饰器)

函数:函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需要调用其函数名即可。

特性: 减少重复代码  是程序变的可扩展   是程序变得易维护

函数参数:

参数可以让你的函数变得跟灵活,不只你能做死循环的动作,还可以根据调用时传参的不同来决定函数内部的执行流程

形参变量

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

实参

可是常量,变量,表达式,函数等,无论实参是何种类型的量,再进行函数调用时,他们都必须有确定的值,以便把这些值传送给形参。

Def calc(x,y):    x,y  形参

Res = x**y

Retrun res

C = calc(a,b)    a,b  实参

默认参数必须要放在位置参数的后边。     def function(name ,age ,course,city=’北京’)

关键参数 def function(name,age,course=’py’,country=‘cn’)      function(’张鉴’,course=’py’,age=22,country=’KOR’)

 非固定参数   -- 方式一 以元祖形式的

def send_alert(msg,*args):    #*之后的可以有很多同类型的参数,打包成元祖,例如账户邮箱等

    for u in args:
        print('warning!!!',u,msg)
send_alert('error!!','alex','ccn','zj')

  

非固定参数  -- 方式二                          非固定参数必须放在最后习惯

uz = ['pig','ccn','zj']
def send_alert(msg,*user):
    for u in user:
        print('warning!!!',u,msg)
send_alert('error!!',*uz)

传字典 就用**

def func(name,*args,**kw):   #**is dic  -zidian
    print(name,args,kw)
dic = {'ccn':'zj'}
func('alex',22,'mashaladi','50w',addr='shandong',num=31344141,**dic) 

函数-返回值

函数外部的代码想要获取函数执行的结果,就可以在函数里用return语句把结果返回

retrun 代表一个函数的结束 ,只要碰到retrun就结束,后边有多少代码都不执行了

函数-局部变量

指定义在函数里边的变量   ,只能在局部生效,函数一点执行结束,变量就消失了在内存里

定义在函数顶层的一级代码的变量,为全局变量。全局变量,全部代码都可以调用

如果想在函数中使用修改全局变量可以使用global     --  不建议使用,一般情况下不用

函数-函数中修改列表中的数据

names = ['Alex','Black','Peiqi']
def change_name():
    #global names
    del names[2]
    names[1] = 'Write'

    names = [‘123’,’465’]     #这个是不可以修改的,如果想要修改就要加上global
    print(names)
change_name()
print(names)

函数-嵌套函数

def func1():
    print('Alex')

    def func2():
        print('Peiqi')
    func2()
func1( )

函数要想执行 必须被调用

函数-作用域

在Python中一个函数就是一个作用域,局部变量其实就是放在作用域中

代码写完之后作用域就生成了,无论函数在哪里调用了,被如何调用了,都会回到最初定义的地方进行向上查找。

函数- 匿名函数  lambda

def calc(x,y):
    if x > y:
        return x**y
    else:
        return x/y
func = lambda  x,y:x**y if x < y else x/y    #shengming  anonymous function

print(func(3,3))
print(calc(3,3))

函数-高阶函数

变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数

可以将函数当做一个函数参数传进来就是高阶函数

只需要满足任意一个条件,即是高阶函数 1.接收一个或多个函数作为输入参数2.return 返回另外一个函数

递归介绍 --递归与栈的关系

递归就是在函数的执行过程中调用自己

def recursion(n):

    #  sum(n)
    print(n)
    recursion(n+1)

recursion(1)

递归的作用:可以解决一些复杂的数学问题,例如斐波那契,汉诺塔

递归的特点:

1.必须有一个明确的结束条件,否则就会变成死循环,最终撑爆系统内存

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

3.递归执行效率不高,递归层次过多会导致栈溢出

求阶乘

def factorial(n):
    
    if n == 1:
        return 1
    return n * factorial(n-1)

print(factorial(10))

尾递归优化:

只保留一层函数的栈数据,他的当前层不需要等待上一层的结果,而是当前层就需要当前层的数据,但是在Python中即使你写了尾递归的优化也是没有用的,Python还是会给你保留上千次的递归。但是要明白概念,C语言是有这种优化的。

def cal(n):
    print(n)
    return cal(n+1)

cal(1)

内置函数 built-in function

abs  求绝对值

all # return True 例如列表中,可能有none,0,all会遍历列表(数据结构)所有元素,只要有一个FALSE,就会显示false

any   与all 相反,只要有一个True  就是True

ascii   返回一个字符的ascii的值

bin   返回一个整数的二进制格式

bool   判断一个数据结构是True or FALSE  bool([]) 空列表、集合、元祖、字典就是FALSE  

bytearray   # 把byte变成bytearray,可修改的数组

bytes   # bytes(“中国”“utf-8”)        

callable   # 判断一个对象是否可以调用,面向对象用的

chr      #返回一个数字的ascii字符,   比如char(97) 返回就是a

Delattr   # 面向对象用的

dir     返回一个对象可调用,操作的属性,功能

divmod     #返回除法的商和余数

enumerate  # 返回列表的索引和元素,比如 d = [“alex”,”jack”],enumerate(d) 之后得到(0,”alex”)(1,”jack”)

eval   # 可以把字符串形式的list,dict,set等,转换成原有的数据类型

exec  # 把字符串格式的代码 ,进行解释并执行,比如exec("print('hello world')"), 就是解释成print(‘hello world’)  并执行

exit  # 退出程序

filter  #对list、dict、set等可迭代的对象进行过滤 ,filter(lambda x: x>10, [1,2,3,4,56,66,77,9,10]),过滤出所有大于10的值   list(filter(lambda x:x > 10,[1,2,3,45,5,5,6,7,77]))        [45, 77]

frozenset      #将一个集合变成只读

globals    #打印全局作用于里的值,全局变量

hash   #  hash函数

hex    #返回一个10进制的16进制表现形式  例如hex(10) 返回’0xa’

id    #查看对象内存地址

isinstance  #判断一个数据结构的类型 isinstance(a,list) a是数据,list是数据类型     True

map  #list(map(lambda x:x**2,a))         a是列表  map类似于filter

max   # 求最大值  max(a)

min   # 求最小值

Object  #面向对象用

oct    #8进制数

ord   #  返回acsii的字符对应的10进制数 ord(‘a’) 返回97

reversed    #可以将列表翻转 和list.reverse()  功能一样  

round     #可以把小数四舍五入成整数

Sum   # 求和   a=[1,2,3]  sum(a)   6

Zip #   a= [1,2,3]   b = ['a','b','c']     list(zip(a,b))  [(1, 'a'), (2, 'b'), (3, 'c')]

名称空间 name spase

Name space  ,顾名思义就是存放名字的地方    举例说明: 变量 x=1 ,1存放于内存中,那名字x存放在哪里呢?名称空间正式存放名字x与1绑定关系的地方。

Python名称空间有4中 :LEGB

Locals: 函数内部的名字空间,局部变量

Enclosing function:在嵌套函数中外部函数的名字空间,如果fun2嵌套在fun1里,对fun2来说,fun1的名字空间就是enclosing

Globals :当前的模块空间,模块就是一些py文件,也就是说,globals()类似全局变量

_builtins_:内置模块空间,也就是内置变量或内置函数的名字空间,存放内置方法之类的

不同变量的作用域不同就是由这个变量所在的名称空间决定的。

闭包现象

def closure():
    name = "alex"

    def inner():
        print("inner",name)
    return inner

func = closure()   # retrun inner mem address

func()

由于name变量被inner函数调用着,名称空间得不到释放,所以在函数外也可以被调用,这种情况情况叫做闭包

函数进阶:装饰器 ,又称语法糖

在不改变源代码和调用方式的情况下扩展一些新的功能:例如加上认证的模式

# -*- coding:utf-8 -*-

account = {
    'is_auth' : False,
    'alex' : '123',
    'jack' : 'abc'
}

def login(func):
    def inner():
        if account['is_auth'] is False:
            username = input('username>>').strip()
            password = input('password>>').strip()
            if username in account :
                if password == account[username]:
                    print('welcome')
                    account['is_auth'] = True
                    func()
                else :
                    print('password is error ,please try again')
            else:
                print('username  not found ')
        else:
            print('user already login')
            func()
    return  inner
def home():
    print("---home page---")

@login
def tencent():
    #login()
    print('---tencetn---')

def alibaba():
    print("---alibaba---")
@login
def jingdong():
    #login()
    print("---jingdong---")

home()
tencent = login(tencent) #这里存放的就是inner的内存地址,inner实现了闭包,不会执行里边的func()
#print(tencent)
jingdong = login(jingdong)

tencent()
jingdong()

列表生成式

现有个需求,现有列表 a = [1,2,3,4,5,6]  要求你把列表里的每一个值加1.  如何是实现

a = [1,2,3,4,5,6775,9]

a = [i+1 for i in a]   # list_builder   列表生成器
print(a)

生成器 -- generator

g = (x * x for x in range(10))
for i in g:
    print(i)

函数生成器

# -*- coding:utf-8 -*-

def febonacci(n):
    a = 0
    b = 1

    count = 0
    while count < n:
        tmp = a
        a = b
        b = tmp + b
        #print(b)
        yield b   #  暂停 return
        count +=1
f = febonacci(20)
print(next(f))
print(next(f))
print(next(f))
print(next(f))

用生成器实现并发编程

# -*- coding:utf-8 -*-

# def g_test():
#     while True:
#         n = yield
#         print("receive from outside:",n)
#
# g = g_test()
# g.__next__()     # 调用生成器,同时会发送None到yield
#
# for i in range(10):
#     g.send(i)        # 调用生成器,同时发送i

# 通过生成器实现多并发效果,线程就是cpu的执行的任务单元
# 吃包子 c1,c2,c3 消费者
# 生产者 product


def cosumer(name):
    print("comsumer %s ready eat "%name)
    while True:
        baozi = yield
        print("comsumer %s start eat num:%s"%(name,baozi))

c1 = cosumer("c1")
c1.__next__()
c2 = cosumer("c2")
c2.__next__()
c3 = cosumer("c3")
c3.__next__()

for i in range(10):
    print("we product %s times baozi"%i)
    c1.send(i)
    c2.send(i)
    c3.send(i)

迭代器

我们已经知道,可以直接作用于for循环的数据类型有以下几种:

1.一类是集合数据类型,如list、tuple、dict、set、str等

2.一类generator,包括生成器和带yield的generator function。

这些可直接作用于for循环的对象是否是iterable,可得带的意思就是可遍历、可循环。

可以使用isinstance()判断一个对象是否是Iterable对象。

迭代器 几乎等同于 生成器

猜你喜欢

转载自www.cnblogs.com/zjaiccn/p/12909662.html