函数-进阶

Posted chao-sir

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数-进阶相关的知识,希望对你有一定的参考价值。

闭包函数

什么是闭包

内部函数包含对外部作用域而非全局作用域的引用

提示:之前我们都是通过参数将外部的值传给函数,闭包提供了另外一种思路,包起来喽,包起呦,包起来哇

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) #查看闭包的元素

# 0
# 1
# 2
# 3

闭包的意义和应用

闭包的意义

返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作 用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用 域

应用领域

延迟计算(原来我们是传参,现在我们是包起来)

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的前提下,为被装饰对象添加上新功能

装饰器的使用

1、无参装饰器

import time
def 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

@timmer   #伪代码是foo = timmer(foo)
def foo():
    time.sleep(3)
    print(‘from foo‘)

# 上述代码装饰器表示将foo封装成函数wrapper的内存地址,
# 下面调用foo()时相当于执行wrapper(),
# 而定义的foo函数在wrapper函数内部被执行了
foo()

2、有参装饰器

def auth(driver=‘file‘):
    def auth2(func):
        def wrapper(*args,**kwargs):
            name=input("user: ")
            pwd=input("pwd: ")

            if driver == ‘file‘:
                if name == ‘justin‘ and pwd == ‘123‘:
                    print(‘login successful‘)
                    res=func(*args,**kwargs)
                    return res
            elif driver == ‘ldap‘:
                print(‘ldap‘)
        return wrapper
    return auth2


# 伪代码是先执行了auth函数将参数传入,
# 转变成@auth2附带一个参数driver="file",
# 转变成foo = auth2(foo),这里外面再套一层仅仅是为了将参数传入而已
@auth(driver=‘file‘)  
def foo(name):
    print(name)

#这里调用foo函数时,相当于调用上面的wrapper函数,
#而被定义的foo函数在wrapper函数中被调用了
foo(‘justin‘)

装饰器语法

# 被装饰函数的正上方,单独一行
@deco1
@deco2
@deco3
def foo():
    pass

foo=deco1(deco2(deco3(foo)))

wraps

from functools import wraps

def deco(func):
    @wraps(func) #加在最内层函数正上方
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper

@deco
def index():
    ‘‘‘哈哈哈哈‘‘‘
    print(‘from index‘)

print(index.__doc__)

叠加多个装饰器

  1. 加载顺序(outter函数的调用顺序):自下而上
  2. 执行顺序(wrapper函数的执行顺序):自上而下
def outter1(func1): #func1=wrapper2的内存地址
    print(‘加载了outter1‘)
    def wrapper1(*args,**kwargs):
        print(‘执行了wrapper1‘)
        res1=func1(*args,**kwargs)
        return res1
    return wrapper1

def outter2(func2): #func2=wrapper3的内存地址
    print(‘加载了outter2‘)
    def wrapper2(*args,**kwargs):
        print(‘执行了wrapper2‘)
        res2=func2(*args,**kwargs)
        return res2
    return wrapper2

def outter3(func3): # func3=最原始的那个index的内存地址
    print(‘加载了outter3‘)
    def wrapper3(*args,**kwargs):
        print(‘执行了wrapper3‘)
        res3=func3(*args,**kwargs)
        return res3
    return wrapper3



@outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址
@outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址
@outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址
def index():
    print(‘from index‘)

print(‘======================================================‘)
index()

函数练习二

题目

# 一:编写函数,(函数执行的时间是随机的)
# 
# 二:编写装饰器,为函数加上统计时间的功能
# 
# 三:编写装饰器,为函数加上认证的功能
# 
# 四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件)要求登录成功一次,后续的函数都无需再输入用户名和密码
# 注意:从文件中读出字符串形式的字典,可以用eval(‘{"name":"justin","password":"123"}‘)转成字典格式
# 
# 五:编写装饰器,为多个函数加上认证功能,要求登录成功一次,在超时时间内无需重复登录,超过了超时时间,则必须重新登录
# 
# 六:编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
# 
# 七:为题目五编写装饰器,实现缓存网页内容的功能:
# 
#       具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中
# 
#       扩展功能:用户可以选择缓存介质/缓存引擎,针对不同的url,缓存到不同的文件中
# 
#
# 八:还记得我们用函数对象的概念,制作一个函数字典的操作吗,来来来,我们有更高大上的做法,在文件开头声明一个空字典,然后在每个函数前加上装饰器,完成自动添加到字典的操作
# 
# 九 编写日志装饰器,实现功能如:一旦函数f1执行,则将消息2017-07-2111:12:11 f1 run写入到日志文件中,日志文件路径可以指定
#   注意:时间格式的获取
#   import time
#   time.strftime(‘%Y-%m-%d %X‘)

迭代器

迭代的概念

‘‘‘
迭代器即迭代的工具,那什么是迭代呢?
迭代是一个重复的过程,每次重复即一次迭代,
并且每次迭代的结果都是下一次迭代的初始值
‘‘‘
while True:  # 只是单纯地重复,因而不是迭代
    print(‘===>‘)

l = [1, 2, 3]
count = 0
while count < len(l):  # 迭代
    print(l[count])
    count += 1

迭代器?可迭代对象?迭代器对象?

1、为何要有迭代器?

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

什么是可迭代对象?

# 可迭代对象指的是内置有__iter__方法的对象,
# 即obj.__iter__,如下

‘hello‘.__iter__
(1,2,3).__iter__
[1,2,3].__iter__
{‘a‘:1}.__iter__
{‘a‘,‘b‘}.__iter__
open(‘a.txt‘).__iter__

什么是迭代器对象?

可迭代对象执行obj.__iter__()得到的结果就是迭代器对象
而迭代器对象指的是即内置有__iter__又内置有__next__方法的对象

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

总结

迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象

迭代器对象的使用

#题目一:
def my_range(start,stop,step=1):
    while start < stop:
        yield start
        start+=step

#执行函数得到生成器,本质就是迭代器
obj=my_range(1,7,2) #1  3  5
print(next(obj))
print(next(obj))
print(next(obj))
print(next(obj)) #StopIteration

#应用于for循环
for i in my_range(1,7,2):
    print(i)
import time
def tail(filepath):
    with open(filepath,‘rb‘) as f:
        f.seek(0,2)
        while True:
            line=f.readline()
            if line:
                yield line
            else:
                time.sleep(0.2)

def grep(pattern,lines):
    for line in lines:
        line=line.decode(‘utf-8‘)
        if pattern in line:
            yield line

for line in grep(‘404‘,tail(‘access.log‘)):
    print(line,end=‘‘)

#测试
with open(‘access.log‘,‘a‘,encoding=‘utf-8‘) as f:
    f.write(‘出错啦404
‘)

for循环机制

  • 基于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循环做了两件事:
1.对数据做了obj.__iter__()方法,拿到一个迭代对象,然后迭代对象执行__next__()方法
2.捕获stopiteration错误,终止继续__next__()

迭代器的优缺点

优点

  • 提供一种统一的、不依赖于索引的迭代方式
  • 惰性计算,节省内存

缺点

  • 无法获取长度(只有在next完毕才知道到底有几个值)
  • 一次性的,只能往后走,不能往前退

next()与__next__()区别

next()是python内置的方法,其本质是调用数据类型的内置__next__()方法

生成器

什么是生成器

一种表现形式是以函数的表现形式

  • 只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,并且不会执行函数内部代码
  • yield返回是类似于return,可以连续返回多个值
def func():
    print(‘====>first‘)
    yield 1
    print(‘====>second‘)
    yield 2
    print(‘====>third‘)
    yield 3
    print(‘====>end‘)


g = func()
print(g)
# <generator object func at 0x0000000002184360>
print(g.__next__())
print(g.__next__())
print(g.__next__())
# ====>first
# 1
# ====>second
# 2
# ====>third
# 3

第二种表现形式是以类似列表解析的形式(生成器表达式)展现

将列表解析的形式[]改为()

# 列子

列表解析: [i for i in range(10)]  # [0,1,2,3,4,5,6,7,8,9]

生成器表达式:(i for i in rage(10))  # <generator object xxx at 0x140feaaa0>

补充

# 使用迭代器的其他的内置函数:sum sort map reduce filter...

写法:sum(i for i in range(10))  # 使用迭代器协议,内存开销小,使用next去取数据,可以去掉生成器表达式外面的()

sum([i for i in range(10)])  # 内存开销大,卡死

生成器就是迭代器

g.__iter__
g.__next__
#因为具备上面的方法,所以生成器就是迭代器,因此可以这么取值
res=next(g)
print(res)

函数练习三

题目

1、自定义函数模拟range(1,7,2)

2、模拟管道,实现功能:tail -f access.log | grep ‘404‘

答案

#题目一:
def my_range(start,stop,step=1):
    while start < stop:
        yield start
        start+=step

#执行函数得到生成器,本质就是迭代器
obj=my_range(1,7,2) #1  3  5
print(next(obj))
print(next(obj))
print(next(obj))
print(next(obj)) #StopIteration

#应用于for循环
for i in my_range(1,7,2):
    print(i)

#题目二
import time
def tail(filepath):
    with open(filepath,‘rb‘) as f:
        f.seek(0,2)
        while True:
            line=f.readline()
            if line:
                yield line
            else:
                time.sleep(0.2)

def grep(pattern,lines):
    for line in lines:
        line=line.decode(‘utf-8‘)
        if pattern in line:
            yield line

for line in grep(‘404‘,tail(‘access.log‘)):
    print(line,end=‘‘)

#测试
with open(‘access.log‘,‘a‘,encoding=‘utf-8‘) as f:
    f.write(‘出错啦404
‘)

协程函数

#yield关键字的另外一种使用形式:表达式形式的yield
def eater(name):
    print(‘%s 准备开始吃饭啦‘ %name)
    food_list=[]
    while True:
        food=yield food_list
        print(‘%s 吃了 %s‘ % (name,food))
        food_list.append(food)

g=eater(‘justin‘)
g.send(None) #对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g)
g.send(‘蒸羊羔‘)
g.send(‘蒸鹿茸‘)
g.send(‘蒸熊掌‘)

函数练习四

题目

1、编写装饰器,实现初始化协程函数的功能

2、实现功能:grep  -rl  ‘python‘  /etc

答案

#题目一:
def init(func):
    def wrapper(*args,**kwargs):
        g=func(*args,**kwargs)
        next(g)
        return g
    return wrapper
@init
def eater(name):
    print(‘%s 准备开始吃饭啦‘ %name)
    food_list=[]
    while True:
        food=yield food_list
        print(‘%s 吃了 %s‘ % (name,food))
        food_list.append(food)

g=eater(‘justin‘)
g.send(‘蒸羊羔‘)






#题目二:
#注意:target.send(...)在拿到target的返回值后才算执行结束
import os
def init(func):
    def wrapper(*args,**kwargs):
        g=func(*args,**kwargs)
        next(g)
        return g
    return wrapper

@init
def search(target):
    while True:
        filepath=yield
        g=os.walk(filepath)
        for dirname,_,files in g:
            for file in files:
                abs_path=r‘%s\\%s‘ %(dirname,file)
                target.send(abs_path)
@init
def opener(target):
    while True:
        abs_path=yield
        with open(abs_path,‘rb‘) as f:
            target.send((f,abs_path))
@init
def cat(target):
    while True:
        f,abs_path=yield
        for line in f:
            res=target.send((line,abs_path))
            if res:
                break
@init
def grep(pattern,target):
    tag=False
    while True:
        line,abs_path=yield tag
        tag=False
        if pattern.encode(‘utf-8‘) in line:
            target.send(abs_path)
            tag=True
@init
def printer():
    while True:
        abs_path=yield
        print(abs_path)


g=search(opener(cat(grep(‘你好‘,printer()))))
# g.send(r‘E:CMSaaadb‘)
g=search(opener(cat(grep(‘python‘,printer()))))
g.send(r‘E:CMSaaadb‘)

yield总结

  1. 函数做成迭代器
  2. 对比return,可以返回多次值,可以挂起/保存函数的运行状态

三元表达式

就是把if判断式进行缩写

name=input(‘姓名>>: ‘)
res=‘SB‘ if name == ‘tom‘ 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 condition1
for 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、优点:省内存,一次只产生一个值在内存中

匿名函数(lambda)

什么是匿名函数

# 匿名就是没有名字
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)
#让其有名字就没有意义

如果要返回多个值需要加上元组括号
func = lambda x,y,z:(x+1,y+1,z+1)
func(1,2,3)
#(2,3,4)

有名字的函数与匿名函数的对比

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

  • 有名函数:循环使用,保存了名字,通过名字就可以重复引用函数功能
  • 匿名函数:一次性使用,随时随时定义

应用:max,min,sorted,map,reduce,filter

lambda和max,min,sorted配合

字典的运算:最小值,最大值,排序
salaries={
    ‘justin‘:3000,
    ‘qf‘:100000000,
    ‘tom‘:10000,
    ‘sb‘:2000
}

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

可以取values,来比较
>>> max(salaries.values())
>>> min(salaries.values())
但通常我们都是想取出,工资最高的那个人名,即比较的是salaries的值,得到的是键
>>> max(salaries,key=lambda k:salary[k])
‘qf‘
>>> min(salaries,key=lambda k:salary[k])
‘sb‘



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

先比较值,值相同则比较键
>>> max(salaries_and_names)
(100000000, ‘qf‘)


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)

map

作用是处理序列中的每一个数据,返回和原序列相同的结果(大数据处理数据)

map来源

array=[1,3,4,71,2]

ret=[]
for i in array:
  ret.append(i**2)
print(ret)


#如果我们有一万个列表,那么你只能把上面的逻辑定义成函数
def map_test(array):
  ret=[]
  for i in array:
    ret.append(i**2)
  return ret

print(map_test(array))


#如果我们的需求变了,不是把列表中每个元素都平方,还有加1,减一,那么可以这样
def add_num(x):
  return x+1

def map_test(func,array):
  ret=[]
  for i in array:
    ret.append(func(i))
  return ret

print(map_test(add_num,array))


#可以使用匿名函数
print(map_test(lambda x:x-1,array))


#上面就是map函数的功能,map得到的结果是可迭代对象
print(map(lambda x:x-1,range(5)))

总结

  • map(有名函数(可以为匿名函数),可迭代对象)
  • 将可迭代对象中每个值都拿出来传入到函数中进行运算,返回最后的结果是一个(可迭代对象,不懂可以查看迭代器原理,通过for循环可以拿到每个值,或list()转化为列表形式)
  • map函数在python2中直接转化为列表形式

reduce

from functools import reduce
#python2中可以直接使用,python3中集成到了functools模块中,需要导入才能使用
#reduce 作用是压缩数据最终返回一个结果(大数据)

#合并,得一个合并的结果
array_test=[1,2,3,4,5,6,7]
array=range(100)

#报错啊,res没有指定初始值
def reduce_test(func,array):
  l=list(array)
  for i in l:
    res=func(res,i)
  return res

# print(reduce_test(lambda x,y:x+y,array))

#可以从列表左边弹出第一个值
def reduce_test(func,array):
  l=list(array)
  res=l.pop(0)
  for i in l:
    res=func(res,i)
  return res

print(reduce_test(lambda x,y:x+y,array))

#我们应该支持用户自己传入初始值
def reduce_test(func,array,init=None):
  l=list(array)
  if init is None:
    res=l.pop(0)
  else:
    res=init
  for i in l:
    res=func(res,i)
  return res

print(reduce_test(lambda x,y:x+y,array))
print(reduce_test(lambda x,y:x+y,array,50))

filter

filter 作用是处理序列中每一个元素,将符合的规则的元素提取出来,放在新序列中并且返回

#过滤字典中以sb_开头的元素,返回最终结果
movie_people=[‘justin‘,‘qf‘,‘tom‘,‘sb_tom‘,‘sb_justin‘,‘sb_qf‘]

def tell_sb(x):
  return x.startswith(‘sb‘)


def filter_test(func,array):
  ret=[]
  for i in array:
    if func(i):
      ret.append(i)
  return ret

print(filter_test(tell_sb,movie_people))


#函数filter,返回可迭代对象
print(filter(lambda x:x.startswith(‘sb‘),movie_people))

map,filter,reduce总结

  • map 处理序列中的每个元素,得到一个结果是一个‘列表’(迭代器),该‘列表’的元素个数及位置与原来一样
  • filter 遍历序列中每个元素,判断每个元素得到布尔值,如果是True则留下来
  • reduce 处理一个序列,然后把序列进行合并操作

当然了,map,filter,reduce,可以处理所有数据类型

lambda和map,reduce,filter结合

name_dic=[
{‘name‘:‘justin‘,‘age‘:1000},
{‘name‘:‘qf‘,‘age‘:10000},
{‘name‘:‘tom‘,‘age‘:9000},
{‘name‘:‘sb‘,‘age‘:18},
]

#利用filter过滤掉千年王八,万年龟,还有一个九千岁
def func(x):
  age_list=[1000,10000,9000]
  return x[‘age‘] not in age_list


res=filter(func,name_dic)
for i in res:
  print(i)

res=filter(lambda x:x[‘age‘] == 18,name_dic)
for i in res:
  print(i)


#reduce用来计算1到100的和
from functools import reduce
print(reduce(lambda x,y:x+y,range(100),100))
print(reduce(lambda x,y:x+y,range(1,101)))



#用map来处理字符串列表啊,把列表中所有人都变成sb,比方tom_sb
name=[‘qf‘,‘justin‘,‘tom‘]

res=map(lambda x:x+‘_sb‘,name)
  for i in res:
    print(i)

内置函数

Python官方标准详情请点击
详细中文解释清点击
技术图片

format

#字符串可以提供的参数 ‘s‘ None
>>> format(‘some string‘,‘s‘)
‘some string‘
>>> format(‘some string‘)
‘some string‘

#整形数值可以提供的参数有 ‘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‘

eval和exec区别

#1、语法
# eval(str,[,globasl[,locals]])
# exec(str,[,globasl[,locals]])

#2、区别
#示例一:
s=‘1+2+3‘
print(eval(s)) #eval用来执行表达式,并返回表达式执行的结果
print(exec(s)) #exec用来执行语句,不会返回任何值
‘‘‘
6
None
‘‘‘

#示例二:
print(eval(‘1+2+x‘,{‘x‘:3},{‘x‘:30})) #返回33
print(exec(‘1+2+x‘,{‘x‘:3},{‘x‘:30})) #返回None

# print(eval(‘for i in range(10):print(i)‘)) #语法错误,eval不能执行表达式
print(exec(‘for i in range(10):print(i)‘))

compile

compile(str,filename,kind)
filename:用于追踪str来自于哪个文件,如果不想追踪就可以不定义
kind可以是:single代表一条语句,exec代表一组语句,eval代表一个表达式
s=‘for i in range(10):print(i)‘
code=compile(s,‘‘,‘exec‘)
exec(code)


s=‘1+2+3‘
code=compile(s,‘‘,‘eval‘)
eval(code)

阶段性练习

题目

1、文件内容如下,标题为:姓名,性别,年纪,薪资

justin male 18 3000
qf male 38 30000
tom female 28 20000
sb female 28 10000

要求:
从文件中取出每一条记录放入列表中,
列表的每个元素都是{‘name‘:‘justin‘,‘sex‘:‘male‘,‘age‘:18,‘salary‘:3000}的形式

2 根据1得到的列表,取出薪资最高的人的信息
3 根据1得到的列表,取出最年轻的人的信息
4 根据1得到的列表,将每个人的信息中的名字映射成首字母大写的形式
5 根据1得到的列表,过滤掉名字以q开头的人的信息
6 使用递归打印斐波那契数列(前两个数的和得到第三个数,如:0 1 1 2 3 4 7...)

7 一个嵌套很多层的列表,如l=[1,2,[3,[4,5,6,[7,8,[9,10,[11,12,13,[14,15]]]]]]],用递归取出所有的值

答案

#1
with open(‘db.txt‘) as f:
    items=(line.split() for line in f)
    info=[{‘name‘:name,‘sex‘:sex,‘age‘:age,‘salary‘:salary}           for name,sex,age,salary in items]

print(info)

#2
print(max(info,key=lambda dic:dic[‘salary‘]))

#3
print(min(info,key=lambda dic:dic[‘age‘]))

#4
info_new=map(lambda item:{‘name‘:item[‘name‘].capitalize(),
                          ‘sex‘:item[‘sex‘],
                          ‘age‘:item[‘age‘],
                          ‘salary‘:item[‘salary‘]},info)

print(list(info_new))

#5
g=filter(lambda item:item[‘name‘].startswith(‘q‘),info)
print(list(g))

#6
#非递归
def fib(n):
    a,b=0,1
    while a < n:
        print(a,end=‘ ‘)
        a,b=b,a+b
    print()

fib(10)
#递归
def fib(a,b,stop):
    if  a > stop:
        return
    print(a,end=‘ ‘)
    fib(b,a+b,stop)

fib(0,1,10)


#7
l=[1,2,[3,[4,5,6,[7,8,[9,10,[11,12,13,[14,15]]]]]]]

def get(seq):
    for item in seq:
        if type(item) is list:
            get(item)
        else:
            print(item)
get(l)

以上是关于函数-进阶的主要内容,如果未能解决你的问题,请参考以下文章

我的C语言学习进阶之旅解决 Visual Studio 2019 报错:错误 C4996 ‘fscanf‘: This function or variable may be unsafe.(代码片段

我的C语言学习进阶之旅解决 Visual Studio 2019 报错:错误 C4996 ‘fscanf‘: This function or variable may be unsafe.(代码片段

我的Android进阶之旅关于Android平台获取文件的mime类型:为啥不传小写后缀名就获取不到mimeType?为啥android 4.4系统获取不到webp格式的mimeType呢?(代码片段

我的Android进阶之旅关于Android平台获取文件的mime类型:为啥不传小写后缀名就获取不到mimeType?为啥android 4.4系统获取不到webp格式的mimeType呢?(代码片段

Atom编辑器入门到精通 Atom使用进阶

Atom编辑器入门到精通 Atom使用进阶