python-基础-4-函数

参考: 教学博客地址1教学博客地址2教学博客地址3

函数

一、函数基础

1.1、什么是函数

        函数的作用是非常重要的,函数可以说是现代编程中最小的模块单元,其本质上是子程序,就是可以独立执行一个功能的程序,函数的操作方法是将函数体压入栈中,然后传入参数,在计算完毕之后,将return的值返回到调用处,然后将函数从栈中释放出去.

        函数对于编程的一般意义来讲,是实现一个特定的功能,并且可以反复调用,减少代码量,在python里没有return语句的话会返回None,所以python里没有真正意义上的过程.所有的都是函数.

        面向对象其实是在函数上发展起来的,对象的方法其实就可以看做函数,当然函数在面向对象的语言中也是函数,可以认为面向对象语言是将函数,基础数据类型这些东西做了一个更高层次的封装.

1.2、为何要用函数之不用函数的问题

#1、 代码的组织结构不清晰,可读性差
#2、 遇到重复的功能只能重复编写实现代码,代码冗余
#3、 功能需要扩展时,需要找出所有实现该功能的地方修改之,无法统一管理且维护难度极大 

1.3、函数分类

#1、内置函数
为了方便我们的开发,针对一些简单的功能,python解释器已经为我们定义好了的函数即内置函数。对于内置函数,我们可以拿来就用而无需事先定义,参考官网:https://docs.python.org/3/library/functions.html

#2、自定义函数
在一些的场景中内置函数是可能无法满足需求的,这就可能需要根据自身或项目要求来定制自己的函数来实现,后续如果遇到相应的场景,直接设定所定义的函数即可。

1.4、自定义函数

#语法,函数名要能反映其意义
def 函数名(参数1,参数2,参数3,...):
    '''注释'''
    函数体
    return 返回的值

# 一个简单的实例
def hello():
    print("你好")
hello()  		# 直接调用就能显示函数的print结果,但是如果没有return返回过程,那么其结果一定是none

# 比如 login
def login():
    username = input("请输入用户名: ")
    password = input("请输入密码: ")

    if username == "xiong" and password == "123":
        return "登陆通过"
    return "错误"

print(login())

1.5、函数原则及定义

# 1、函数需要先定义,然后在调用, 但A函数调用B,但B函数在A函数之后,那就会报错
def a():
    print("这里是a")
    b()
a()   # 先引用了a函数,但是b函数还没有引用到内存中,就会出现 b函数没有被定义

def b():
    print("这里是b")

# 2、函数定义阶段
    # 函数在引用时啥都不会干,只会加载到内存中,但它一旦被调用就会执行函数内的过程

1.6、有参无参

def play():
    print("玩耍")

def get(num):
    print("你的号码是: {}".format(num))

play()
get(12332112222)

1.7、函数返回值

return-> pring时会直接打印 None
return 1个值->返回1个值
return 逗号分隔多个值->元组
  • 什么时候该有返回值?
    • 调用函数,经过一系列的操作,最后要拿到一个明确的结果,则必须要有返回值
    • 通常有参函数需要有返回值,输入参数,经过计算,得到一个最终的结果
  • 什么时候不需要有返回值?
    • 调用函数,仅仅只是执行一系列的操作,最后不需要得到什么结果,则无需有返回值
    • 通常无参函数不需要有返回值

1.8、形参与实参

# 形参即变量名,实参即变量值,函数调用时,将值绑定到变量名上,函数调用结束,解除绑定
  • 位置参数
按照从左到右的顺序定义的参数
	位置形参:必选参数
	位置实参:按照位置给形参传值

def test(v1,v2):		# 2、函数test(形参v1,v2)
	print(v1,v2)		# 3、当调用之后,获取实参 3 5

test(3,5)		# 1、调用 test(传递实参 3 5)
  • 关键字参数
按照key=value的形式定义的实参,无需按照位置为形参传值
注意的问题:
    1. 关键字实参必须在位置实参右面
    2. 对同一个形参不能重复传值

def local(v1, status=False):			 # 2、关键字参数必须在最右边
    return v1 if status else "木有状态"	   # 3、三元表达式 获取任意一个值返回其状态
print(local("hello"))     				 # 1、当有关键字参数时,可以不用传递 默认就是false


# 失败案例, 这种是不可以的
    # non-default argument follows default argument
    def the_test(v1, status=False, v2):	
        return v1 if status else "木有状态"		

    # duplicate argument 'v1' in function definition
    def the_test(v1, v2, v1):      
        return v1 if v2 else "木有状态"
  • 默认参数
# 可以传值也可以不传值,经常需要变得参数定义成位置形参,变化较小的参数定义成默认参数(形参)
注意的问题:
    1. 只在定义时赋值一次
    2. 默认参数的定义应该在位置形参右面
    3. 默认参数通常应该定义成不可变类型

# 与关键字参数差不多
  • 可变长参数

    可变长指的是实参值的个数不固定
    而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参对应有两种解决方案来完整地存放它们,分别是*args,**kwargs
    
    #################################### *args ####################################
    def test(x, y, *args):
        print("x: {} \ny: {} \nargs: {}".format(x, y, args))
    
    
    test(1, 2, 3, 4, 5, 6, 7, 8)  # args: (3, 4, 5, 6, 7, 8)
    
    # 如果不做处理,那么传递的就是一个元组加列表的形式
    test(1, 2, [1, 2], [111, 22])  # args: ([1, 2], [111, 22])
    
    # 通过 *[] 类似于迭代直接列表做了一个for循环传递到*args当中
    test(1, 2, *[1, 2, 3, 5, 6])  # args: (1, 2, 3, 5, 6)
    
    
    #################################### **kwargs ####################################
    def test(x, **kwargs):
        print("x: {} \nkwargs: {}".format(x, kwargs))
    
    
    # kwargs: {'k': '123', 'k2': '234', 'k3': '345', 'k4': '456'}
    test(1, k="123", k2="234", k3="345", k4="456")
    
    # 通过迭代的方式传递,先解开然后在传值, 如果直接传字典会报错
    test(1, **{
          
          'k': '123', 'k2': '234', 'k3': '345', 'k4': '456'})
    
    
    ############################ *args + **kwargs ####################################
    def test(*args, **kwargs):
        print("args: {}\nkwargs: {}".format(args, kwargs))
    
    
    # args: (1, 2, 3) kwargs: {'k': '123', 'k2': '234'}
    test(1, 2, 3, k="123", k2="234")
    
    # args: (1, 2, 3) kwargs: {'k': '123', 'k2': '234'}
    test(*[1, 2, 3], **{
          
          'k': '123', 'k2': '234'})
    

二、对象及嵌套

2.1、函数对象

函数是第一类对象,即函数可以当作数据传递

#1 可以被引用
#2 可以当作参数传递
#3 返回值可以是函数
#3 可以当作容器类型的元素

# 示例  特性
def foo():
    print("foo")

def bar():
    print("bar")

dic = {
    
    
    "foo": foo,
    "bar": bar
}

while True:
    chiose = input(">>: ").strip()
    if chiose in dic:
        dic[chiose]()

2.2、嵌套调用

def max(x, y):
    return x if x > y else y

def check(a, b, c, d):
    res1 = max(a, b)			# check嵌套max使用
    res2 = max(c, d)			# 两两比较,在得出最大值
    return max(res1, res2)

print(check(11, 2, 3, 4))

三、名称空间与作用域

  • 什么是名称空间
#名称空间:存放名字的地方,三种名称空间,(之前遗留的问题x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方)
  • 名称空间的加载顺序

    python test.py
    #1、python解释器先启动,因而首先加载的是:内置名称空间
    #2、执行test.py文件,然后以文件为基础,加载全局名称空间
    #3、在执行文件的过程中如果调用函数,则临时产生局部名称空间
    
    # 名字的查找顺序
        局部名称空间--->全局名称空间--->内置名称空间
        #需要注意的是:在全局无法查看局部的,在局部可以查看全局的,如下示例
    
    def foo():
        max_num = 111		 # 2、min_num相对于foo来说就是一个局部名称变量了
    
        def foo_two():
            min_num = 2222    # 1、max_num相对于foo_two来说也是一个全局变量
            return min_num
        foo_two()
        return max_num
    
    foo()     
    # 然后Py里直接执行 max_num 会报出 NameError: name 'max_num' is not defined
    
  • 作用域

    #1、作用域即范围
        - 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效
        - 局部范围(局部名称空间属于该范围):临时存活,局部有效
    #2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下
    
    x=11111
    def f1():
        def f2():
            print(x)
        return f2
    
    x = 22222
    
    def f3(func):
        x = 33333
        func()
    
    f3(f1())     # 最终的结果是 22222
    # 先到 全局11111- 22222, 执行f3->f1->f2,f2此时是22222,然后进入x=33333,执行函数func 由于x=33333是局部范围,所以并没有更改x的全局变量,然后在打印 结果为22222
    
  • 作用域查询

    #3、查看作用域:globals(),locals()
    
    LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
    locals 是函数内的名字空间,包括局部变量和形参
    enclosing 外部嵌套函数的名字空间(闭包中常见)
    globals 全局变量,函数定义所在模块的名字空间
    builtins 内置模块的名字空间
    
  • global与nonlocal关键字

    global 将局部变量 修改为全局变量, 这个关键字并不建议使用,如果引用全局可变对象,也就是按引用传递,最好将引用复制一份,否则对全局可变对象直接操作,会修改全局可变对象
    
    max = 123
    def f1():
        # global max		# 1、如果引用了global那么它会修改全局变量
        max = 12321
        print(max)
    
    f1()
    print(max)    			# 2、这里得到的结果就是12321
    
    # nonlocal  如果想指定上一层的局部变量,用nonlocal声明
    
    min = "最小值"
    def f2():
        min = "f2里头的"
    
        def f3():
            nonlocal min      # 只修改函数内的上一级
            min = "f3里的"
            print("*" * 10, min)
            
        def f4():     
            print(min)   # f3 修改了f2的min值,此时f4得到的全局变量 f2的min就是 f3的结果了
    
        f3()
        f4()
        print(min)
    
    f2()
    print(min)
    
    ############################  结果为  ############################
        ********** f3里的
        f3里的
        最小值
    

四、闭包

4.1、什么是闭包?

# 内部函数包含对外部作用域而非全局作用域的引用
# 提示:之前我们都是通过参数将外部的值传给函数,闭包提供了另外一种思路,将函数包裹起来

def t1():
    n = 0
    def t2():
        nonlocal n  # 修改上层的n值
        x = n  		# 重新赋值x
        n += 1  	# 每次执行函数+1
        return x  	# 返回修改之后的值

    return t2  # 返回x

c = t1()
print(c())  # 0
print(c())  # 1
print(c())  # 2
print(c())  # 3
print(c.__closure__[0].cell_contents)  #查看闭包的元素  下一次就是4了

4.2、闭包的意义与应用

#闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
#应用领域:延迟计算(原来我们是传参,现在我们是包起来)

from urllib.request import urlopen

def index(url):
    def get():
        return urlopen(url).read()
    return get

bd=index("http://www.baidu.com")   # 得到的是一个内存对象
print(bd().decode('utf-8'))

五、装饰器

装饰器就是闭包函数的一种应用场景

为什么用装饰器

程序中的函数就是具备某一功能的工具, 装饰器就是一个函数,
定义装饰器就是定义一个函数, 只不过装饰器的功能是就是用来给其它函数添加额外的功能,
装饰器( 被装饰的对象 )本身其实是任意可调用的对象, 

软件的维护应该遵循开放封闭原则
开放封闭的原则是: 软件一旦上线运行后对修改源代码是封闭的,对扩展功能是开放的
    装饰器的实现必须遵循的两大原则
   1、不修改被装饰对象的源代码
   2、不修改被装饰对象的调用方式

装饰器语法糖 
	在被装饰的函数上加上 @装饰器 (闭包函数)  等于 函数名=装饰器(函数名)

5.1、无参装饰器

5.1、示例一

简单demo 写法一:  有一定的局限性

import time

def home():
    print("welcome home ")
    time.sleep(2)

def times(func):
    def warpper():
        start = time.time()
        func()     # 执行被装饰的函数
        end = time.time()
        print("装饰器执行的时长为: {}".format(end-start))
    return warpper    # 拿到并返回装饰函数的内存地址

home = times(home)
home()

--------------------------------------------------

demo 第二个

def index():
    print("welcome to index..")
    time.sleep(1)
    return 123

def home(tip):
    print("this price {}".format(tip))

def timmer(func):
    def warpper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        end = time.time()
        print("程序运行时间: {}".format(end-start))
        return res
    return warpper

index = timmer(index)
print(index())
home = timmer(home)
home(100)

--------------------------------------------------

demo 第三个    装饰器语法糖的方式
import time

timmer函数不变

@timmer         #  等于 index = timmer(index)
def index():
	.....
	
@timmer         #  等于 home=timmer(home)
def home(tip):
    print("this price {}".format(tip))


print(index())
home(100)

5.2、有参装饰器

import time

current_user = {"user": None}
def auth(eng):
    def timeer(func):
        def wrapper(*args, **kwargs):
            if current_user["user"]:
                res = func(*args, **kwargs)
                return res

            username = input("请输入用户: ").strip()    # 输入用户 去掉空格
            pwd = input("请输入密码: ").strip()         # 输入密码 去掉空格
            if eng == "file":
                if username == "xiong" and pwd == "123":
                    current_user["user"] = "xiong"
                    print("登陆成功")
                else:
                    print("登陆失败")
            elif eng == "mysql":
                print("mysql登陆")
            res = func(*args, **kwargs)
            return res
        return wrapper
    return timeer

timeer = auth(eng="file")

@timeer
def index():
    print("this's index page")
    time.sleep(1)

@auth(eng="file")
def home():
    print("this's home page")
    time.sleep(1)

index()
home()

装饰器- wraps

**@wraps**接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。

demo-1 - 不带参数的装饰器

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
from functools import wraps

check_auth = {
    
    "user": None}


def auth(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        if check_auth["user"]:
            res = func(*args, **kwargs)
            return res
        user = input("username >>>: ").strip()
        passwd = input("passwd >>>: ").strip()
        if user == "xiong" and passwd == "123":
            res = func(*args, **kwargs)
            return res
        return "登陆失败"

    return wrapper

@auth         # 相当于是 login=auth(login)
def login():
    return "登陆到了主页"


print(login())

demo-2 - 带参数的装饰器

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
from functools import wraps

check_auth = {
    
    "user": None}


def check_auth_types(auth_type="file"):
    def auth(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if check_auth["user"]:
                res = func(*args, **kwargs)
                return res
            if auth_type == "file":
                print("文件认证")
                user = input("username >>>: ").strip()
                passwd = input("passwd >>>: ").strip()
                if user == "xiong" and passwd == "123":
                    res = func(*args, **kwargs)
                    return res
            if auth_type == "mysql":
                return func(*args, **kwargs),"数据库认证"
            return "登陆失败"

        return wrapper

    return auth


x = check_auth_types(auth_type="mysql")

@check_auth_types(auth_type="mysql")  # 也可以是 @x
def login():
    return "登陆到了主页"
#  check_auth_types 传递参数,返回给了auth, 做为有参装饰器继续往里传递执行

print(login())

多个装饰器

# 叠加多个装饰器
# 1. 加载顺序(outter函数的调用顺序):自下而上
# 2. 执行顺序(wrapper函数的执行顺序):自上而下

六、迭代器

迭代器概念

# 迭代器即迭代的工具,那什么是迭代呢?
# 迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值

while True: # 只是单纯地重复,因而不是迭代
    print('===>') 	# 一个无脑的死循环

lis=[1,2,3]
count=0
while count < len(lis): # 迭代 重复的过程,但每次迭代都是下一次的初始值
    print(lis[count])
    count+=1			# 每次加1, 如果没有+1 那就不是下一次的初始值 == 一个无脑的死循环

为何要有迭代器?什么是可迭代对象?什么是迭代器对象?

#1、为何要有迭代器?
	对于序列类型:字符串(str)、列表(list)、元组(tuple),我们可以使用索引的方式迭代取出其包含的元素。但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则必须找出一种不依赖于索引的迭代方式,这就是迭代器

#2、什么是可迭代对象?
    可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,如下 
    # 也可通过 dir() 可查看内置函数方法 __iter__
    'hello'.__iter__
    (1,2,3).__iter__
    [1,2,3].__iter__
    {
    
    'a':1}.__iter__
    {
    
    'a','b'}.__iter__
    open('a.txt').__iter__

#3、什么是迭代器对象?
    可迭代对象执行obj.__iter__()得到的结果就是迭代器对象
    执行迭代器对象是__next__得到的是迭代器下一个值
    执行迭代器对象的__iter__得到的仍然是迭代器本身
    而迭代器对象指的是即内置有__iter__又内置有__next__方法的对象

文件类型是迭代器对象
open('a.txt').__iter__()
open('a.txt').__next__()

# 使用
dic = {
    
    'a': 1, 'b': 2, 'c': 3}
iter_dic = dic.__iter__() #得到迭代器对象,迭代器对象即有__iter__又有__next__,但是:迭代器.__iter__()得到的仍然是迭代器本身
print(iter_dic, type(iter_dic))
# <dict_keyiterator object at 0x0000020BAF49BB88> <class 'dict_keyiterator'>

print(iter_dic.__next__())
print(iter_dic.__next__())
print(iter_dic.__next__())
# print(iter_dic.__next__())  # StopIteration

#4、注意:
迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象

for循环 - 迭代器

dic = {
    
    'a': 1, 'b': 2, 'c': 3}

for i in dic:  	   # dic.__iter__()  得到迭代器对象
    print(dic[i])  # 每次循环都是 xx.__next__() 获取值,直到StopIteration

# for循环的工作原理
# 1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
# 2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
# 3: 重复过程2,直到捕捉到异常StopIteration,结束循环

迭代器优缺点

#优点:
  - 提供一种统一的、不依赖于索引的迭代取值方式
  - 惰性计算,节省内存

#缺点:
  - 迭代器的取值不如按照索引的方式灵活,它只能往后取而不能往前退
  - 无法预测迭代器的个数
  - 无法获取长度(只有在next完毕才知道到底有几个值)
  - 一次性的,只能往后走,不能往前退

七、生成器-yield

# 生成器 generator
	生成器指的是生成器对象,可以由生成器表达式得到,也可以使用yield关键字得到一个生成器函数,那么函数名()的到的结果就是生成器,并且不会执行函数内部代码
    
# 生成器函数
	函数体中包含yield语句的函数,返回生成器对象
    生成器对象,是一个可迭代对象,是一个迭代器
    生成器对象,是延迟计算、惰性求值的

示例

def yie():
    for i in range(5):
        yield i


print(type(yie))
print(type(yie()))   # <class 'generator'>
y = yie()			 # 通过生成器生成的对象都是一个内存地址 
for i in y:
    print(i)

普通的函数调用 fn(),函数会立即执行完毕,但是生成器函数可以使用next函数多次执行
生成器函数等价于生成器表达式,只不过生成器函数可以更加复杂

yield from

def yie():
    for x in range(100): yield x

# 等价于
def yie():
    yield from range(100)

yield from 是python3.3出现的新语法,  是fro item in iterable: yield item形式的语法糖

八、表达式

1.1、三元表达式

条件成立时的返回值, if 条件 else 条件不成立时时的返回值

def check(x,y):
    if x > y:
        return x
    else:
        return y

x=10
y=20

# 三元表达式   如果x 大于 y 最左边为x (true),最右边为如果不大于的结果
res = x if x > y else y   # 如上的函数可以简化为这种三元表达式
print(res)

1.2、列表生成式

# 重要: 把列表推导式的[]换成()就是生成器表达式

li=[]
for i in range(10):
    li.append(i)
print(li)

# 在列表中循环, 然后将循环的值放到左右就能直接append了
li2 = [i for i in range(10)]
print(li2)

# 列表生成式 只能 for if 不能跟else
name = ["xiong", "xiong2", "xiong3"]
li3 = [i for i in name if i not in "xiong"]
print(li3)

# 循环1到10如果小于5 那么i就加1,
li4 = [i+1 for i in range(1,10) if i<5]
print(li4)

1.3、生成器表达式

# 把列表推导式的[]换成()就是生成器表达式

x = (i for i in range(10))
print(x, type(x))
# <generator object <genexpr> at 0x00000231AB5725E8> <class 'generator'>

# 使用生成器的优点:省内存,一次只产生一个值在内存中,每次执行next只会取出一个

with open("a.txt", "r") as files:
    # 生成器刚开始造的时候 代码不会执行, 只能在.__next() 调用的时候才会运行
    nums = (len(line) for line in files)
    print(max(nums))

1.4、字典生成式

keys=["name", "age", "sex"]
values = ["xiong", "100", "male"]
# zip 拉链函数 将两个值对应成元组 如 (name, xiong)
print(list(zip(keys,values)))

res = {k:v for k,v in zip(keys, values)}
print(res)
# {'name': 'xiong', 'age': '100', 'sex': 'male'}

1.5、元组生成器

tuple(random.randint(0, 255) for i in range(3))
(241, 97, 220)

九、递归与二分法

1.1、什么是递归

# 1、什么是递归
	递归调用是函数嵌套调用的一种特殊形式,函数在调用时,直接或间接调用了自身,就是递归调用
   	递归就是一个无何止的重复过程, 递归必须要有一个明确的结束条件

# 2、代码特点
    - 函数内部的 代码 是相同的,只是针对 参数不同,处理的结果不同
    - 当参数满足一个条件时,函数不再执行
      - 这个通常称为递归的出口,否则会出现死循环

# 3、递归阶段
    递归必须要有两个明确的阶段
    	递推: 一层一层递归调用下去,每进入下一层递归问题的规模都必须有所减少
        回溯: 递归必须要有一个明确的结束条件,在满足该条件时结束递推,开始一层一层回溯	
    递归的精髓在于通过不断地重复逼近一个最终的结果

# 4、递归层级
    print(sys.getrecursionlimit())  # 获取递归的层级, 1000层
    sys.setrecursionlimit(next())	# 设置递归的层级,但没有多大的意义,如果太多可能会导致内存崩掉

# 5、为什么使用递归
	递归本身就是一个重复的过程,while循环本身也是做一个重复的过程,递归能做的事 循环也都能满足,但比如是如下这种使用while就会显得比较麻烦,而直接使用递归就能得出想要的结果
    
l = [1, [2, [3, [4, [5, [6, [7, [8]]]]]]]]

def dl(l):
    for its in l:
        if type(its) is list:
            dl(its)
        else:
            print(its)
dl(l)

# 示例2 
def age(n):
    if n == 1: return 10     
    return age(n-1)+2      // 递推到n等于1时返回10,  然后取到10每次加2  

print(age(5)) 循环五次

1.2、递归-二分法

# 查找列表
search_list = [1, 3, 5, 7, 9, 11, 23, 33, 44, 112, 115, 125, 136, 147, 199]

def search(search_list, num):
    two_search = len(search_list) // 2  # # 每次取一半
    if two_search == 0:
        print("没有这个")
        return
    if num > search_list[two_search]:
        n = search_list[two_search:]
        search(n, num)
    elif num < search_list[two_search]:
        n = search_list[:two_search + 1]
        search(n, num)
    else:
        print("找着了")

search(search_list, 112)

十、匿名函数

# 有名函数,调用函数名可以一直重复使用
# 有名函数
def fun(x, y):
    return x + y

print(fun(1, 4))

# 匿名函数, 通常于其它函数一起使用,直接执行就的是一个内存地址, :后的x+y就相当于是return x+y
print(lambda x, y: x + y)  # <function <lambda> at 0x000002948ACD47B8>
# 与函数有相同的作用域,但是匿名意味着引用计数为0,使用一次就释放,除非让其有名字

示例

salaries = {
    
    
    "axiong": 10000,
    "wen": 99000,
    "hei": 19999,
    "bai": 22222
}

def fun(k):
    return salaries[k]

max工作原理:

1、 先将可迭代对象变成 迭代器对象
2、 res=next(可迭代器对象), 将res当作参数传递给max函数,然后将该函数的返回值当作判断依据

# 最大值就是w,但func却只需要一次性使用,这里就可以直接使用匿名函数了
# max(iterable, *[, default = obj, key = func]) -> value
# max(arg1, arg2, *args, *[, key = func]) -> val, key=funue
print(max(salaries, key=fun))
print(max(salaries, key=lambda k:salaries[k]))    # wen
print(min(salaries, key=lambda k:salaries[k]))    # axiong

sorted

# sorted 排序
print(sorted(names, reverse=True))  # 从大到小
print(sorted(names, reverse=False))  # 从小到大

# 与匿名函数进行配置 sorted(可迭代对象, key=匿名函数, 排序=True/False)
print(sorted(names, key=lambda x:x, reverse=True))
print(sorted(names, key=lambda x:x, reverse=False))

map工作原理

1、 先将可迭代对象变成 迭代器对象
2、 res=next(可迭代器对象), 将res当作参数传递给第一个参数指定的函数,然后将该函数的返回值当作map的结果之一
3、 映射: 将原来的值映射成新的值 

# 映射,将列表的旧值映射为新的值
m_name = map(lambda x: x + "XXS", names)  # ['heiXXS', 'baiXXS', 'hongXXS', 'nvXXS']
print(list(m_name))  # 如果不使用list 打印的话  打印的结果就是迭代器对象,需要通过 __next__

# 与如下的列表生成式相等
m_name = [name + "xxxx" for name in names]
print(m_name)

filter工作原理

1、 先将可迭代对象变成 迭代器对象
2、 res=next(可迭代器对象), 将res当作参数传递给第一个参数指定的函数,然后filter会判断函数的返回值 的真假,如果为真则留下res

names = ["xiongge", "wo", "ni", "hao"]

#  列表生成器
res = [name for name in names if name.endswith("ge")]
print(res)

# filter 过滤器  filter(匿名函数, 可迭代对象)
f_name = filter(lambda x: not x.endswith("ge"), names)
print(f_name)  # <filter object at 0x000002B9433EB240>
print(list(f_name))  # ['wo', 'ni', 'hao']
# 使用lamba过滤  filter   过滤某个条件     
语法:  lambda i: i %2, range(10)   等于是下面这个函数 
def t1(i):
    temp=[]
    for i in range(10):
        temp.append('{0}'.format(i%2))
    return temp

y=list(filter(lambda i:i %2, range(10)))
print(y)  # [1, 3, 5, 7, 9]

map() 可以批量处理数据,与filter() 相比,输入可以是多个可迭代对象
xx = map(lambda x:x, range(10))
print(list(xx))   # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

使用递归打印斐波那契数列

# 使用递归打印斐波那契数列

def fib(n):
    a, b = 0, 1
    while a < n:
        print(a, end=" ")
        a, b = b, a + b
    print(" ")


fib(20)


def flb(a, b, stop):
    if a > stop:
        return
    print(a, end="\t")
    flb(b, a + b, stop)

# 一个嵌套很多层的列表,如l=[1,2,[3,[4,5,6,[7,8,[9,10,[11,12,13,[14,15]]]]]]],用递归取出所有的值
l = [1, 2, [3, [4, 5, 6, [7, 8, [9, 10, [11, 12, 13, [14, 15]]]]]]]
def gl(l):
    if type(l) is list:
        for li in l:
            gl(li)
    else:
        print(l, end="\t")

gl(l)

十一、内置函数

官方内置函数

Built-in Functions
abs() delattr() hash() memoryview() set()
all() dict() help() min() setattr()
any() dir() hex() next() slice()
ascii() divmod() id() object() sorted()
bin() enumerate() input() oct() staticmethod()
bool() eval() int() open() str()
breakpoint() exec() isinstance() ord() sum()
bytearray() filter() issubclass() pow() super()
bytes() float() iter() print() tuple()
callable() format() len() property() type()
chr() frozenset() list() range() vars()
classmethod() getattr() locals() repr() zip()
compile() globals() map() reversed() __import__()
complex() hasattr() max() round()

11.1、需要了解的函数

# 列表中所有值为真,则为真,如果为空也是真
	print(all([1, 2, 3, 4, 5]))     # True

# 有一个bool值为真,则为真,  如果为空则是false
	print(any([1, 0, False]))       # True

# 十进制转二进制
	print(bin(11))                  # 0b1011
    
# oct  十进制转八进制
    print(oct(9))                   # 0o11

# hex 十进制转十六进制
	print(hex(19))                  # 0x13

# chr()  将数字转换成字符
	print(chr(103))                 # g

# ord 将字符串转成数字
	print(ord("g"))                 # 103

# dir   判断函数里的所有属性
	print(dir(True))                # ['__abs__', '__add__',....]

# pow (3,2,2)   3的2次方取余
	print(pow(5,2,2))               # 1
    
# round(3.5)  四舍五入
    print(round(3.99))              # 4
    
callable()   判断函数是否可被调用

divmod(10,3)     分页使用,  比如31 就是  3,1 总共有30页 余1

猜你喜欢

转载自blog.csdn.net/u010304195/article/details/112916031