天天看点

Python基础—内置函数、匿名函数、递归函数一、内置函数二、匿名函数三、递归函数

文章目录

  • 一、内置函数
    • 1 作用域相关
    • 2 其他
      • Ⅰ 字符串类型代码的执行:
      • Ⅱ 输入输出相关:
      • Ⅲ 数据类型相关:
      • Ⅳ 内存相关:
      • Ⅴ 文件操作相关
      • Ⅵ 模块操作相关
      • Ⅶ 帮助方法
      • Ⅷ 调用相关
      • Ⅸ 查看参数所属类型的所有内置方法
    • 3 数字相关
    • 4 数据结构相关
  • 二、匿名函数
    • 1 匿名函数格式的说明:
    • 2 有名函数与匿名函数的对比:
    • 3 lambda与内置函数结合使用
  • 三、递归函数
    • 1 递归调用的定义
    • 2 递归调用的两个阶段:递推,回溯
    • 3 python中的递归
    • 4 二分法

一、内置函数

截止到python版本3.6.2,现在python一共为我们提供了68个内置函数。它们就是python提供给你直接可以拿来使用的所有函数。

Python基础—内置函数、匿名函数、递归函数一、内置函数二、匿名函数三、递归函数

把这些函数分成了6大类:

Python基础—内置函数、匿名函数、递归函数一、内置函数二、匿名函数三、递归函数

1 作用域相关

Python基础—内置函数、匿名函数、递归函数一、内置函数二、匿名函数三、递归函数

基于字典的形式获取局部变量和全局变量

globals()——获取全局变量的字典

locals()——获取执行本方法所在命名空间内的局部变量的字典

2 其他

Python基础—内置函数、匿名函数、递归函数一、内置函数二、匿名函数三、递归函数

Ⅰ 字符串类型代码的执行:

eval() 将字符串类型的代码执行并返回结果

print(eval('1+2+3+4'))

# 10
           

**exec()**将自字符串类型的代码执行

print(exec("1+2+3+4"))
exec("print('hello,world')")

# None
# hello,world
           

compile 将字符串类型的代码编译。代码对象能够通过exec语句来执行或者eval()进行求值。

参数说明:

  1. 参数source:字符串或者AST(Abstract Syntax Trees)对象。即需要动态执行的代码段。
  2. 参数 filename:代码文件名称,如果不是从文件读取代码则传递一些可辨认的值。当传入了source参数时,filename参数传入空字符即可。
  3. 参数model:指定编译代码的种类,可以指定为 ‘exec’,’eval’,’single’。当source中包含流程语句时,model应指定为‘exec’;当source中只包含一个简单的求值表达式,model应指定为‘eval’;当source中包含了交互式命令语句,model应指定为’single’。

流程语句使用exec

code1 = 'for i in range(0,10): print (i)'
compile1 = compile(code1, '', 'exec')
exec(compile1)

# 0
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
           

简单求值表达式用eval

code2 = '1 + 2 + 3 + 4'
compile2 = compile(code2, '', 'eval')
eval(compile2)

           

交互语句用single

code3 = 'name = input("please input your name:")'
compile3 = compile(code3,'','single')
name #执行前name变量不存在

#
Traceback (most recent call last):
  File "D:\pystudy\fullstack\作业练习\脚本.py", line 3, in <module>
    name #执行前name变量不存在
NameError: name 'name' is not defined
           
>>> exec(compile3) #执行时显示交互命令,提示输入
please input your name:'psych'
>>> name #执行后name变量有值
"'psych'"
           

Ⅱ 输入输出相关:

input() 输入

s = input("请输入内容 : ")  #输入的内容赋值给s变量
print(s)  #输入什么打印什么。数据类型是str
           

print() 输出

print源码剖析

def print(self, *args, sep=' ', end='\n', file=None): # known special case of print
    """
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    file:  默认是输出到屏幕,如果设置为文件句柄,输出到文件
    sep:   打印多个值之间的分隔符,默认为空格
    end:   每一次打印的结尾,默认为换行符
    flush: 立即把内容输出到流文件,不作缓存
    """
           

file关键字的说明

f = open('tmp_file','w')
print(123,456,sep=',',file = f,flush=True)
           

Ⅲ 数据类型相关:

type(o) 返回变量o的数据类型

Ⅳ 内存相关:

id(o) o是参数,返回一个变量的内存地址

hash(o) o是参数,返回一个可hash变量的哈希值,不可hash的变量被hash之后会报错。

t = (1,2,3)
l = [1,2,3]
print(hash(t))  #可hash
print(hash(l))  #会报错

'''
结果:
TypeError: unhashable type: 'list'
'''
           

hash函数会根据一个内部的算法对当前可hash变量进行处理,返回一个int数字。

注:每一次执行程序,内容相同的变量hash值在这一次执行过程中不会发生改变。

Ⅴ 文件操作相关

open() 打开一个文件,返回一个文件操作符(文件句柄)

操作文件的模式有r,w,a,r+,w+,a+ 共6种,每一种方式都可以用二进制的形式操作(rb,wb,ab,rb+,wb+,ab+)

可以用encoding指定编码.

Ⅵ 模块操作相关

__import__导入一个模块

导入模块:

import time
           

__import __:

os = __import__('os')
print(os.path.abspath('.'))
           

Ⅶ 帮助方法

在控制台执行help()进入帮助模式。可以随意输入变量或者变量的类型。输入q退出

或者直接执行help(o),o是参数,查看和变量o有关的操作。。。

Ⅷ 调用相关

callable(o),o是参数,看这个变量是不是可调用。

如果o是一个函数名,就会返回True

def func():pass
print(callable(func))  #参数是函数名,可调用,返回True
print(callable(123))   #参数是数字,不可调用,返回False
           

Ⅸ 查看参数所属类型的所有内置方法

dir() 默认查看全局空间内的属性,也接受一个参数,查看这个参数内的方法或变量

print(dir(list))  #查看列表的内置方法
print(dir(int))  #查看整数的内置方法
           

3 数字相关

Python基础—内置函数、匿名函数、递归函数一、内置函数二、匿名函数三、递归函数

数字——数据类型相关:bool,int,float,complex

数字——进制转换相关:bin,oct,hex

数字——数学运算:abs,divmod,min,max,sum,round,pow

4 数据结构相关

Python基础—内置函数、匿名函数、递归函数一、内置函数二、匿名函数三、递归函数

序列——列表和元组相关的:list和tuple

序列——字符串相关的:str,format,bytes,bytearry,memoryview,ord,chr,ascii,repr

bytearray:

ret = bytearray('psych',encoding='utf-8')
print(id(ret))
print(ret[0])
ret[0] = 65
print(ret)
print(id(ret))

# 2074162046256
# 97
# bytearray(b'Psych')
# 2074162046256
           

memoryview:

ret = memoryview(bytes('你好',encoding='utf-8'))
print(len(ret))
print(bytes(ret[:3]).decode('utf-8'))
print(bytes(ret[3:]).decode('utf-8'))

# 6
# 你
# 好

           

format:

  1. 函数功能将一个数值进行格式化显示。
  2. 如果参数format_spec未提供,则和调用str(value)效果相同,转换成字符串格式化。
>>> format(3.1415936)
'3.1415936'
>>> str(3.1415926)
'3.1415926'
           
  1. 对于不同的类型,参数format_spec可提供的值都不一样
#字符串可以提供的参数,指定对齐方式,<是左对齐, >是右对齐,^是居中对齐
print(format('test', '<20'))
print(format('test', '>20'))
print(format('test', '^20'))

#整形数值可以提供的参数有 'b' 'c' 'd' 'o' 'x' 'X' 'n' None
>>> format(3,'b') #转换成二进制
'11'
>>> format(97,'c') #转换unicode成字符
'a'
>>> format(11,'d') #转换成10进制
'11'
>>> format(11,'o') #转换成8进制
'13'
>>> format(11,'x') #转换成16进制 小写字母表示
'b'
>>> format(11,'X') #转换成16进制 大写字母表示
'B'
>>> format(11,'n') #和d一样
'11'
>>> format(11) #默认和d一样
'11'

#浮点数可以提供的参数有 'e' 'E' 'f' 'F' 'g' 'G' 'n' '%' None
>>> format(314159267,'e') #科学计数法,默认保留6位小数
'3.141593e+08'
>>> format(314159267,'0.2e') #科学计数法,指定保留2位小数
'3.14e+08'
>>> format(314159267,'0.2E') #科学计数法,指定保留2位小数,采用大写E表示
'3.14E+08'
>>> format(314159267,'f') #小数点计数法,默认保留6位小数
'314159267.000000'
>>> format(3.14159267000,'f') #小数点计数法,默认保留6位小数
'3.141593'
>>> format(3.14159267000,'0.8f') #小数点计数法,指定保留8位小数
'3.14159267'
>>> format(3.14159267000,'0.10f') #小数点计数法,指定保留10位小数
'3.1415926700'
>>> format(3.14e+1000000,'F')  #小数点计数法,无穷大转换成大小字母
'INF'

#g的格式化比较特殊,假设p为格式中指定的保留小数位数,先尝试采用科学计数法格式化,得到幂指数exp,如果-4<=exp<p,则采用小数计数法,并保留p-1-exp位小数,否则按小数计数法计数,并按p-1保留小数位数
>>> format(0.00003141566,'.1g') #p=1,exp=-5 ==》 -4<=exp<p不成立,按科学计数法计数,保留0位小数点
'3e-05'
>>> format(0.00003141566,'.2g') #p=1,exp=-5 ==》 -4<=exp<p不成立,按科学计数法计数,保留1位小数点
'3.1e-05'
>>> format(0.00003141566,'.3g') #p=1,exp=-5 ==》 -4<=exp<p不成立,按科学计数法计数,保留2位小数点
'3.14e-05'
>>> format(0.00003141566,'.3G') #p=1,exp=-5 ==》 -4<=exp<p不成立,按科学计数法计数,保留0位小数点,E使用大写
'3.14E-05'
>>> format(3.1415926777,'.1g') #p=1,exp=0 ==》 -4<=exp<p成立,按小数计数法计数,保留0位小数点
'3'
>>> format(3.1415926777,'.2g') #p=1,exp=0 ==》 -4<=exp<p成立,按小数计数法计数,保留1位小数点
'3.1'
>>> format(3.1415926777,'.3g') #p=1,exp=0 ==》 -4<=exp<p成立,按小数计数法计数,保留2位小数点
'3.14'
>>> format(0.00003141566,'.1n') #和g相同
'3e-05'
>>> format(0.00003141566,'.3n') #和g相同
'3.14e-05'
>>> format(0.00003141566) #和g相同
'3.141566e-05'
           

序列:reversed,slice

reversed:

l = (1,2,23,213,5612,342,43)
print(l)
print(list(reversed(l)))

# (1, 2, 23, 213, 5612, 342, 43)
# [43, 342, 5612, 213, 23, 2, 1]
           

slice:

l = (1,2,23,213,5612,342,43)
sli = slice(1,5,2)
print(l[sli])

# (2, 213)
           

数据集合——字典和集合:dict,set,frozenset

数据集合:len,sorted,enumerate,all,any,zip,filter,map

filter:

filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。

例如,要从一个list [1, 4, 6, 7, 9, 12, 17]中删除偶数,保留奇数,首先,要编写一个判断奇数的函数:

def is_odd(x):
    return x % 2 == 1
           

然后,利用filter()过滤掉偶数:

list(filter(is_odd, [1, 4, 6, 7, 9, 12, 17]))

# [1, 7, 9, 17]
           

利用filter(),可以完成很多有用的功能,例如,删除 None 或者空字符串:

def is_not_empty(s):
    return s and len(s.strip()) > 0
>>>list(filter(is_not_empty, ['test', None, '', 'str', '  ', 'END']))
           

结果:

注意: s.strip(rm) 删除 s 字符串中开头、结尾处的 rm 序列的字符。

当rm为空时,默认删除空白符(包括’\n’, ‘\r’, ‘\t’, ’ '),如下:

>>> a = ' 123'
>>> a.strip()
'123'

>>> a = '\t\t123\r\n'
>>> a.strip()
'123'
           

map:

Python中的map函数应用于每一个可迭代的项,返回的是一个结果list。如果有其他的可迭代参数传进来,map函数则会把每一个参数都以相应的处理函数进行迭代处理。map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。

有一个list, L = [1,2,3,4,5,6,7,8],我们要将f(x)=x^2作用于这个list上,那么我们可以使用map函数处理。

>>> L = [1,2,3,4,] 
>>> def pow2(x): 
... return x*x 
... 
>>> list(map(pow2,L))
[1, 4, 9, 16] 
           

sorted:

对List、Dict进行排序,Python提供了两个方法

对给定的List L进行排序:

  • 方法1.用List的成员函数sort进行排序,在本地进行排序,不返回副本
  • 方法2.用built-in函数sorted进行排序(从2.4开始),返回副本,原始输入不变

参数说明:

  • iterable:是可迭代类型;
  • key:传入一个函数名,函数的参数是可迭代类型中的每一项,根据函数的返回值大小排序;
  • reverse:排序规则. reverse = True 降序 或者 reverse = False 升序,有默认值。
  • 返回值:有序列表

例:

列表按照其中每一个值的绝对值排序

l1 = [1,3,5,-2,-4,-6]
l2 = sorted(l1,key=abs)
print(l1)
print(l2)

# [1, 3, 5, -2, -4, -6]
# [1, -2, 3, -4, 5, -6]
           

二、匿名函数

为了解决那些功能很简单的需求而设计的一句话函数

有名函数:

def calc(n):
    return n**n
print(calc(10))
           

换成匿名函数:

calc = lambda n:n**n
print(calc(10))
           
Python基础—内置函数、匿名函数、递归函数一、内置函数二、匿名函数三、递归函数

1 匿名函数格式的说明:

函数名 = lambda 参数 :返回值

1.参数可以有多个,用逗号隔开

2.匿名函数不管逻辑多复杂,只能写一行,且逻辑执行结束后的内容就是返回值

3.返回值和正常的函数一样可以是任意数据类型

2 有名函数与匿名函数的对比:

有名函数:循环使用,保存了名字,通过名字就可以重复引用函数功能

匿名函数:一次性使用,随时随时定义

3 lambda与内置函数结合使用

字典的运算:最小值,最大值,排序
salaries={
    'egon':3000,
    'alex':100000000,
    'wupeiqi':10000,
    'yuanhao':2000
}

迭代字典,取得是key,因而比较的是key的最大和最小值
>>> max(salaries)
'yuanhao'
>>> min(salaries)
'alex'

可以取values,来比较
>>> max(salaries.values())
>>> min(salaries.values())

但通常我们都是想取出,工资最高的那个人名,即比较的是salaries的值,得到的是键
>>> max(salaries,key=lambda k:salary[k])
'alex'
>>> min(salaries,key=lambda k:salary[k])
'yuanhao'



也可以通过zip的方式实现
salaries_and_names=zip(salaries.values(),salaries.keys())

先比较值,值相同则比较键
>>> max(salaries_and_names)
(100000000, 'alex')


salaries_and_names是迭代器,因而只能访问一次
>>> min(salaries_and_names)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: min() arg is an empty sequence



sorted(iterable,key=None,reverse=False)
           

三、递归函数

1 递归调用的定义

递归调用是函数嵌套调用的一种特殊形式,函数在调用时,直接或间接调用了自身,就是递归调用

直接调用本身:

def f1():
    print('from f1')
    f1()
f1()
           

间接调用本身:

def f1():
    print('from f1')
    f2()

def f2():
    print('from f2')
    f1()
f1()
           

调用函数会产生局部的名称空间,占用内存,因为上述这种调用会无需调用本身,python解释器的内存管理机制为了防止其无限制占用内存,对函数的递归调用做了最大的层级限制

可以修改递归最大深度;

import sys
sys.getrecursionlimit()
sys.setrecursionlimit(2000)

def f1(n):
    print('from f1',n)
    f1(n+1)
f1(1)
           

虽然可以设置,但是因为不是尾递归,仍然要保存栈,内存大小一定,不可能无限递归,而且无限制地递归调用本身是毫无意义的,递归应该分为两个明确的阶段,回溯与递推

2 递归调用的两个阶段:递推,回溯

回溯就是从外向里一层一层递归调用下去,回溯阶段必须要有一个明确地结束条件,每进入下一次递归时,问题的规模都应该有所减少(否则,单纯地重复调用自身是毫无意义的)

递推就是从里向外一层一层结束递归

3 python中的递归

python中的递归效率低且没有尾递归优化

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

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

递归的使用:

  1. 必须有一个明确的结束条件
  2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
  3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

例:递归函数实现三级菜单

menu = {
    '北京': {
        '海淀': {
            '五道口': {
                'soho': {},
                '网易': {},
                'google': {}
            },
            '中关村': {
                '爱奇艺': {},
                '汽车之家': {},
                'youku': {},
            },
            '上地': {
                '百度': {},
            },
        },
        '昌平': {
            '沙河': {
                '老男孩': {},
                '北航': {},
            },
            '天通苑': {},
            '回龙观': {},
        },
        '朝阳': {},
        '东城': {},
    },
    '上海': {
        '闵行': {
            "人民广场": {
                '炸鸡店': {}
            }
        },
        '闸北': {
            '火车战': {
                '携程': {}
            }
        },
        '浦东': {},
    },
    '山东': {},
}
           
def threeLM(dic):
     while True:
         for k in dic:print(k)
         key = input('input>>').strip()
         if key == 'b' or key == 'q':return key
         elif key in dic.keys() and dic[key]:
             ret = threeLM(dic[key])
             if ret == 'q': return 'q'
 
threeLM(menu)
           

4 二分法

想从一个按照从小到大排列的数字列表中找到指定的数字,遍历的效率太低,用二分法(算法的一种,算法是解决问题的方法)可以极大低缩小问题规模

例如:

l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]

观察这个列表,这是不是一个从小到大排序的有序列表?

如果这样,假如要找的数比列表中间的数还大,是不是直接在列表的后半边找就行了?

Python基础—内置函数、匿名函数、递归函数一、内置函数二、匿名函数三、递归函数

这就是二分查找算法!

简单版二分法:

l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]

def func(l,aim):
    mid = (len(l)-1)//2
    if l:
        if aim > l[mid]:
            func(l[mid+1:],aim)
        elif aim < l[mid]:
            func(l[:mid],aim)
        elif aim == l[mid]:
            print("bingo",mid)
    else:
        print('找不到')
func(l,66)
func(l,6)
           

升级版二分法:

def search(num,l,start=None,end=None):
    start = start if start else 0
    end = end if end is not None else len(l) - 1
    mid = (end - start)//2 + start
    if start > end:
        return None
    elif l[mid] > num :
        return search(num,l,start,mid-1)
    elif l[mid] < num:
        return search(num,l,mid+1,end)
    elif l[mid] == num:
        return mid