第七章 Python 内置函数、匿名函数

本文深入探讨递归函数的概念及使用注意事项,包括递归的基本原理、递归调用的限制与应用场景。同时,详细介绍了Python内置函数如max、min、sorted等的使用方法,并结合匿名函数展示了它们在实际编程中的应用。

 

 

第1章 递归函数

函数递归调用:在调用一个函数的过程中直接或间接地调用该函数本身,称之为函数的递归调用

 

### 在函数中调用自己本身 递归函数 超出了函数递归的最大限制

### 直接
def func():
    print('from func')
    func()

func()          # RecursionError: maximum recursion depth exceeded while calling a Python object

# Python中递归的效率低
# 在Python中没有伪递归优化

### 间接
def foo ():
    print('from foo')
    bar()

def bar():
    print('from bar')
    foo()

foo()

 

1.1 递归的过程

# age(5)=age(4)+2
# age(4)=age(3)+2
# age(3)=age(2)+2
# age(2)=age(1)+2
# age(1)=18
#
# age(n)=age(n-1)+2
# age(1)=18 #n=1

 

def age(n):
    if n == 1:
        return 18
    return age(n-1)+2

>>> 26

 

递归执行分为两个阶段:递推和回溯

 

 

1.2 python中的递归

python中的递归效率低,需要在进入下一次递归时保留当前的状态,在其他语言中可以有解决方法:尾递归优化,即在函数的最后一步(而非最后一行)调用自己,尾递归优化:http://egon09.blog.51cto.com/9161406/1842475

但是python又没有尾递归,且对递归层级做了限制

 

### 总结递归的使用:

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

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

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

 

1.3 递归的层级

import sys
print(sys.getrecursionlimit())

>>> 1000
sys.setrecursionlimit(1500) # 修改递归的层级,没必要 这样会造成占用更多的层级

 

1.4 使用场景

# 取出列表中所有的元素
l=[1,2,[3,[4,[5,[6,7,[8,9,[10,[11,[12,]]]]]]]]]
def search(l):
    for item in l:
        if type(item) is list:  # 如果循环出来的元素是列表的话
            search(item)        # 继续向下
        else:
            print(item)         # 打印出来
search(l)

 

1.5 总结递归调用

#总结递归调用:
#1:进入下一次递归时,问题的规模必须降低
#2:递归调用必须要有一个明确的结束条件
#3:在python中没有尾递归优化,递归调用的效率就是不高

 

 

 

 

 

第2章 二分法

l=[1,2,10,30,33,99,101,200,301,402]
# 从小到大排列的数字列表 例如要找到10 循环比3次即可 那要是1W个元素呢
# 如果全部遍历一次 列表又非常大 效率极低
# 如何高效解决,使用二分法
# 将列表从中间切分 然后对比两边的数据 得到条件后继续切分 直到得出结果 问题规模每次都缩小一半
# 例如要找到200
# 不知道切多少次能够切完 使用递归 找到结果终止

def binary_search(l,num):
    print(l)
    mid_index=len(l)//2       # 地板除得整数,得到中间的索引
    print(mid_index,l[mid_index])
    if num > l[mid_index]:    # 如果值比中间索引的值大 那么该值在列表的右边
        #  in the right
        l=l[mid_index+1:]       # 切一刀 中间的值到最后,中间的值已经做过一次比较 所以  + 1 到最后
        binary_search(l,num)
    elif num < l[mid_index]:
        # in the left
        l=l[:mid_index]         # 顾头不顾尾,取不到mid_index
        binary_search(l,num)
    else:
        print('find it')

binary_search(l,200)

 

[1, 2, 10, 30, 33, 99, 101, 200, 301, 402]

5 99

[101, 200, 301, 402]

2 301

[101, 200]

1 200

find it

 

 


# 如果要找到的值不在列表中呢?
# [1, 2, 10, 30, 33, 99, 101, 200, 301, 402]
# 5 99
# [30, 33]
# [1, 2, 10, 30, 33]
# 1 33
# []

 

 

 

def binary_search(l,num):
    print(l)
    if len(l) > 0:  # 列表不为空,则证明还有值是可以执行二分法逻辑的
        mid_index=len(l)//2       # 地板除得整数,得到中间的索引

        print(mid_index,l[mid_index])
        if num > l[mid_index]:    # 如果值比中间索引的值大 那么该值在列表的右边
            #  in the right
            l=l[mid_index+1:]             # 切一刀 中间的值到最后,中间的值已经做过一次比较 所以  + 1 到最后
            binary_search(l,num)
        elif num < l[mid_index]:
            # in the left
            l=l[:mid_index]         # 顾头不顾尾,取不到mid_index
            binary_search(l,num)
        else:
            print('find it')
            return
    else
:  # 列表为空,则证明根本不存在要查找的值
        print('not exists')
        return

binary_search(l,20)

 

第3章 匿名函数

# 函数名可以指向内存地址
def func(x,y,z=1):
    return x+y+z

print(func)     # <function func at 0x0000009910729950>
# 函数名加括号传参
print(func(1,2,3))

 

# 匿名函数
# 1、没有函数名,直接加参数
# 2、匿名函数体只有一行代码
# 3、函数体自带return

print(lambda x,y,z=1:x+y+z)         # 这就是个值 可以直接打印 <function <lambda> at 0x0000009F99619950>
f=lambda x,y,z=1:x+y+z              # 给一个名字 <function <lambda> at 0x000000902A2C9950>
print(f)

print(f(1,2,3))                      # 直接调用 但是匿名函数本意是不要名字 这样调用还是给了名字

# 匿名函数的应用场景:

# 应用于一次性场景,临时用 临时定义

 

第4章 内置函数

 

 

#   注意:内置函数id()可以返回一个对象的身份,返回值为整数。这个整数通常对应与该对象在内存中的位置,但这与python的具体实现有关,不应该作为对身份的定义,即不够精准,最精准的还是以内存地址为准。

is运算符用于比较两个对象的身份,等号比较两个对象的值,内置函数type()则返回一个对象的类型

 

#   更多内置函数:https://docs.python.org/3/library/functions.html?highlight=built#asci

4.1 优先掌握

 

 

 

 

4.2 面向对象

classmethod
staticmethod
property

getattr
hasattr
setattr
delattr

 

 

 

 

4.3 其他了解

4.3.1 abs( ) 取绝对值

# abs() 取绝对值 负数得正数
print(abs(-1))

>>> 1

 

4.3.2 all ( ) 判断可迭代参数的bool值

# all() 可迭代对象里面取出来每一个值,每一个值的bool值都为真,那么all最终的结果才为真
# 判断给定的可迭代参数 iterable 中的所有元素是否不为 0、''、False 或者 iterable 为空,如果是返回 True,否则返回 False。

# 存在一个为空的元素  存在一个为0的元素 返回Flase
# 如果可迭代对象为空 返回Ture

 

print(all([1,2,3,4]))
print(all([1,2,'a',None]))
print(all([1,2,'a',0]))
print(all([]))

 

True

False

False

True

 

4.3.3 any( ) 判断可迭代参数的bool值

 

any() 函数用于判断给定的可迭代参数 iterable 是否全部为空对象,如果都为空、0、false,则返回 False,如果不都为空、0、false,则返回 True

print(any(['a', 'b', 'c', 'd']))  # 列表list,元素都不为空或0
print(any(['a', 'b', '', 'd']))  # 列表list,存在一个为空的元素
print(any([0, '', False])  ) # 列表list,元素全为0,'',false
print(any([]))空列表

True

True

False

False

4.3.4 bin,oct,hex 进制转换

print(bin(10))  # 转二进制
print(oct(10))  # 转八进制
print(hex(10))  # 转十六进制

 

4.3.5 bool 布尔值

bool() 函数用于将给定参数转换为布尔类型,如果没有参数,返回 False
bool 是 int 的子类。
bool值为假的情况:None,空,0.False

 

4.3.6 bytes返回一个新的 bytes 对象

# bytes 返回一个新的 bytes 对象
#unicode-----encode------bytes
print('hello'.encode('utf-8'))
print(bytes('hello',encoding='utf-8'))

>>> b'hello'

>>> b'hello'

 

4.3.7 callable  # 卡乐伯 是否可以被调用

# callable() 函数用于检查一个对象是否是可调用的。如果返回True,object仍然可能调用失败;但如果返回False,调用对象ojbect绝对不会成功。
# 对于函数, 方法, lambda 函式, 类, 以及实现了 __call__ 方法的类实例, 它都返回 True 。
print(callable(bytes))

True

 

4.3.8 chr,ord 字符与数字转换

返回值是当前整数对应的ascii字符。
print(chr(65))  # A  将数字转成字符
print(chr(35))  # #

print(ord('A')) # 65 将字符转成数字
print(ord('#')) # 35

print(chr(65))  # 65 - 90 是 A 到 Z
print(chr(90))

 

4.3.9 frozenset 不可变集合

s1={1,2,3,4} # s=set{1,2,3,4} 可变集合 有add方法
print(type(s1))

# frozenset 不可变集合 没有add方法
s2=frozenset({1,2,3,4})
print(type(s2))

 

4.3.10  dir 返回模块的属性列表

import sys
print(dir(sys))

 

['__displayhook__', '__doc__', '__excepthook__', '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_enablelegacywindowsfsencoding', '_getframe', '_git', '_home', '_xoptions', 'api_version', 'argv', 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_wrapper', 'getallocatedblocks', 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettrace', 'getwindowsversion', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'is_finalizing', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'set_asyncgen_hooks', 'set_coroutine_wrapper', 'setcheckinterval', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout', 'thread_info', 'version', 'version_info', 'warnoptions', 'winver']

 

 

4.3.11 divmod 返回商和余数

# divmod 返回商和余数 可以用来实现分页的功能
print(divmod(10,3)) #(3, 1)

 

4.3.12 enumerate 返回元祖,并为每个元素加上索引显示


l=['a','b','c','d']
res=enumerate(l)
print(res)          # <enumerate object at 0x00000024A4F41A68>
for i in res:
    print(i)

>>> (0, 'a')
>>> (1, 'b')
>>> (2, 'c')
>>> (3, 'd')

 

 

l=['a','b','c','d']
res=enumerate(l)
print(res)          # <enumerate object at 0x00000024A4F41A68>
for index,item in res:
    print(index,item)

 

4.3.13 globals,locals 查看全局作用域和局部作用域

print(globals()) # 内置和全局中的名字 字典形式展示

 

4.3.14 hash

# hash
print(hash('abcefg123'))   
print(hash('abcefg123'))
>>> -159098785945555233
>>> -159098785945555233

 

4.3.15 help 查看帮助信息

def func():
    '''
    test function
   
:return:
    '''
   
pass

print(help(func))

 

 

4.3.16 id 反映变量在内存中位置

# id 反映变量在内存中位置,是id号 并不是在内存的真实位置

# id 只是python解释器实现的功能
a=10
print(a,id(a),type(a))

>>> 10 1407764432 <class 'int'>

 

4.3.17 isinstance 判断变量类型

x=1
print(type(x))
print(type(x) is int)
print(isinstance(x,int))

>>> <class 'int'>
>>> True
>>> True

 

4.3.18 pow平方后的取模运算

# pow
print(pow(3,2,2)) # 3 ** 2 % 2 =1

 

4.3.19 repr 把对象转成字符串

# repr 把对象转成字符串
print(type(str(1)))  # <class 'str'>  str 给用户用的
print(type(repr(1))) # <class 'str'>  repr是给解释器用的

 

4.3.20 reversed 反转

l=[1,'a',2,'c']
print(list(reversed(l)))
print(l)

 

4.3.21 round 保留指定小数,并且四舍五入

round 保留指定小数,并且四舍五入
print(round(3.478,2))  # 3.48

4.3.22 slice( ) 切片

l=[1,2,3,4,5,6]
print(l[0:4:2]) # 顾头不顾尾[1, 3]
# 给一个切片对象 可以给很多列表使用
s=slice(0,4,2)
print(l[s])     # [1, 3]

 

4.3.23 sorted() 排序 只能同类型去排

# sorted() 排序 只能同类型去排
l=[1,10,4,3,-1]
print(sorted(l)) # 从小到大
print(sorted(l,reverse=True))   # 从小到大

 

4.3.24 sum 求和

# sum() 求和
print(sum([1,2,3]))
# 传一个生成器
print(sum(i for i in  range(10)))

 

4.3.25  zip 拉链函数

# zip 拉链函数
s='hello'   # 序列类型
l=[1,2,3,4,5]   # 序列类型
res=zip(s,l)

# 对应取值形成元组,多出来的不生成元组,只找对应部分
print(list(res)) # [('h', 1), ('e', 2), ('l', 3), ('l', 4), ('o', 5)]

 

 

4.3.26  __import__ 通过字符串形式来导入一个模块

m_name=input('>>>: ')

if m_name == 'sys':
    # import m_name   # 变量名= 'sys' 有需求通过字符串形式来导入一个模块 这就要用__import__
    m=__import__(m_name)
    # print(m_name.path)  # No module named 'm_name'
    print(m)    # <module 'sys' (built-in)>
    print(m.path) # ['D:\\Python_Learn\\day5', 'D:\\Python_Learn', 'C:\\Python36\\python36.zip', 'C:\\Python36\\DLLs', 'C:\\Python36\\lib', 'C:\\Python36', 'C:\\Python36\\lib\\site-packages']

 

 

 

第5章 内置函数与匿名函数的使用

5.1 求工资最高的人名 max

#与匿名函数结合使用
# max min.sorted
# filter map reduce

salaries={
    'egon':3000,
    'alex':10000000,
    'wupeiqi':10000,
    'yuanhao':2000
}

#求工资最高的人名 max
print(max(salaries))    # yuanhao  max循环字典得的是key 比较的是key 字符串的比较 “首字母”
print(max(salaries.values()))       # 10000000 .values() 取得是字典的值 但是要得到的是人名
# 如果能有一种方式 让 一个值对应一个key

# 序列比较和字符串是一样的 一个个比较 1=1 'y'>'h'
# t1=(1,'h',3,4,5,6)
# t2=(1,'y',3)
# print(t1 > t2) # False

# # 带入刚才的问题
# t1=(10000000,'alex')
# t2=(3000,'egon')
# print(t1 > t2) # 比较第一个已经分出大小 ,然后再取人名

print(salaries.values())    # dict_values([3000, 10000000, 10000, 2000])
print(salaries.keys())      # dict_keys(['egon', 'alex', 'wupeiqi', 'yuanhao'])

# 然后使用zip 拉链
print(list(zip(salaries.values(),salaries.keys())))  # zip 可以将两个序列类型 合并成为一个元组
# [(3000, 'egon'), (10000000, 'alex'), (10000, 'wupeiqi'), (2000, 'yuanhao')]
print(max(zip(salaries.values(),salaries.keys()))[1]) # (10000000, 'alex') 最大 然后取人名 # alex

 

 

# max 已经提供了这种方法
# max(salaries,key=)   # key= 想要的结果 这里要字典的key 人名  # key 告诉max 按照什么来比较
# 在这里我指定key=薪资 但是max的输出结果 还是按照字典中的key 也就是人名来输出最后的比较结果
# key=比较的依据

# # 通过key获取value
# def get_value(name):
#     return salaries[name]       # 就一行函数体 使用匿名函数即可
#
# max(salaries,key=lambda name:salaries[name])
# max函数默认比较的是字典的key,也就是人民 但是后面指定了 key= 所以讲salaries传给了lambda 的name,这个匿名函数获取了薪资
# 所有max每次获取到每个key人名 比较的是薪资  最后得到的是人名

# max 的for 循环 取字典一个值 就会传给后面的匿名函数
print(max(salaries,key=lambda name:salaries[name])) # alex

 

 

def get_value(name):
    return salaries[name]
l=[]
for name in salaries:
    res=get_value(name)
    l.append(res)
print(max(l))

 

5.2 求工资最低的人名 min

print(min(salaries,key=lambda name:salaries[name])) # yuanhao

 

5.3 排序 sorted 默认从小到大

# 排序 sorted
salaries={
    'egon':3000,
    'alex':10000000,
    'wupeiqi':10000,
    'yuanhao':2000
}

# 按照名字排序
# print(sorted(salaries))  # ['alex', 'egon', 'wupeiqi', 'yuanhao'] 默认从小到大
def get_value(name):
    return salaries[name]
# 按照工资排序
# print(sorted(salaries,key=get_value)) # ['yuanhao', 'egon', 'wupeiqi', 'alex']


# 反转 从大到小
# print(sorted(salaries,key=get_value,reverse=True)) # ['alex', 'wupeiqi', 'egon', 'yuanhao']

# 匿名函数的写法
print(sorted(salaries,key=lambda name:salaries[name])) # ['yuanhao', 'egon', 'wupeiqi', 'alex']
print(sorted(salaries,key=lambda name:salaries[name],reverse=True)) # ['alex', 'wupeiqi', 'egon', 'yuanhao']

 

5.4 合并 reduce

# redice 合并
# 在python2里是内置函数 python3要导入functools
from functools import reduce
print(reduce(lambda x,y:x+y,range(101))) #方法,序列,初始值(默认none) # 5050
print(reduce(lambda x,y:x+y,range(101),100))  # 5150

# 原理:reduce 如果有初始值,会把初始值作为第一个值
# for循环后面的序列 得到一个值
# 实际上现在有两个值了 初始值和后面循环的值
# 然后将这两个值 传给前面的函数 x,y 然后会得到第一次计算加法的结果 == 0+100 100
# 然后在for循环 再得到一个值1,那么现在 x=100 ,y=1 传给函数 ==101 然后继续循环
# 没有指定默认值会先循环一次range(101) 得到的第一个值 作为初始值 所以初始值是0

 

5.5 生成器与迭代器 自己做map方法

names=['alex','wupeiqi','yuanhao','egon'] # 每一个元素映射成一个sb结尾
# def my_map(seq):
#     new_list=[]
#     for item in seq:
#         item=item+'_SB'
#         new_list.append(item)
#     return new_list
#
# print(my_map(names))

# 如果列表非常大 会很占内存 所有要用 yield
def my_map(seq):
    for item in seq:
        item=item+'_SB'
        yield
item          # generator object my_map at 0x00000077DEB310F8 生成器 都是 迭代器 省内存


res=my_map(names)
print(next(res))
print(next(res))
print(next(res))
print(next(res))

 

def my_map(func,seq):
    for item in seq:
        yield func(item)          # generator object my_map at 0x00000077DEB310F8 生成器 都是 迭代器 省内存

res=my_map(lambda x:x+'_SB',names)
print(next(res))

 

5.6 filter() 过滤出bool值为真的值

# filter() 过滤出bool值为真的值
# 过滤出结尾SB
names=['alex_SB','wupeiqi_SB','yuanhao_SB','egon']
print(filter(lambda name:name.endswith('SB'),names))
print(list(filter(lambda name:name.endswith('SB'),names))) 

# ['alex_SB', 'wupeiqi_SB', 'yuanhao_SB']

 

 

5.7 eval、compile和exec

# eval 将字符串转成命令执行
# 作用域:全局 和 局部 全都是字典形式 eval 会先找局部
cmd='print(x)'
x=1
eval(cmd)
eval(cmd,{'x':0},{'x':123}) # 123 走的局部
eval(cmd,{'x':0},{'y':123}) # 0 走的全局

compile # 编译
s='for i in range(10):print(i,x)'
code=compile(s,'','exec')   # 代表编译成可执行的代码
print(code)         # <code object <module> at 0x0000009747261270, file "", line 1>
# exec(code)  # exec执行编译之后的结果
exec(code,{},{'x':111}) # 局部作用域

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

                                                     

转载于:https://www.cnblogs.com/touchlixiang/p/7702996.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值