Python中函数的高级特性和高阶函数

函数的多个返回值

def hello():
    return "hello","world"
result = hello()
print(result,type(result))#('hello', 'world') <class 'tuple'>
返回的多个值是元组类型
res1,res2 = hello()
print(res1,res2)  #hello world

函数多个返回值的练习

i = 2
print(isinstance(i,int)) #True 判断数据类型

函数名get_max_min_avg()
函数可以传递任意多个数字, 并且保证是整形或者浮点型;
如果满足条件, 返回最大值, 最小值,和平均值;
如果不满足条件, 返回None

def is_int_float(t):
    for i in t:
        if not isinstance(i,(int,float)):
            return False
    else:
        return True
def get_max_min_avg(*args):
    if is_int_float(args):
        return max(args),min(args),sum(args)/len(args)
print(get_max_min_avg(12,2,3,23,34))

形参的顺序

常用:必选 》 默认 》 可变(元组类型) 》 关键字(字典类型)
特例:可选参数 》 默认参数
易错点:形参的默认参数类型,必须是不可变数据类型,如果是可变的函数执行一次,默认参数的值就会改变一次。

def fun(l=[]):
    l.append("hello")
    return l
print(fun())  # ['hello']
print(fun())  #['hello', 'hello']
print(fun())  #['hello', 'hello', 'hello']

高级特性

迭代

主要是字典的迭代

d = dict(a=1,b=2)
for k,v in d.items():
    print(k,v)

判断一个对象是否可迭代

首先需要倒入模块
from collections import Iterable

print(isinstance(1,Iterable)) #False
print(isinstance('hello',Iterable))#True
print(isinstance({1,2,3},Iterable))#True

高级特性

列表生成式 :生成列表的公式
列表生成式的四种写法

最简单的,只有简单的for循环
[i for i in range(10)]
for循化里面嵌套有if判断
[i for i in range(10) if i%2==0]
for循环里面有ifelse
[ i**2 if i%2==0  i**3 for i in range(10)]
for循环里面嵌套for循环
[ i+j for i in 'abc' for j in '123']

列表生成式的练习

利用列表生成式随机生成100个IP地址

import random  #随机生成一个整数的模块
list = ['172.25.254.' + str(random.randint(1,255)) for i in range(100)]
print(list)
print(len(list))

1~100之间能被三整除的数的平方

def is_div_three(n):
    if n % 3 ==0:
        return True
list = [i**2 for i in range(1,101) if is_div_three(i)]
print(list)

找出/etc/目录中所有以.conf结尾的文件,并把这些文件名转化为大写的文件名

import os  #将目录中的文件名转换为列表的模块
list = [i.upper() for i in os.listdir('/etc') if i.endswith('.conf')]
print(list)

给定一个正整数,编写程序计算有多少对质数的和等于输入的这个正整数,并输出结果。输入值小于1000。

def is_num(i):
    if i <= 0:
        return False
    elif i ==1 or i == 2:
        return True
    else:
        for n in range(2,i):
            if i%n == 0:
                return False
        else:
            return True
num = int(input("请输入一个正整数:"))
list = [item for item in range(num) if is_num(item)]
list1 = [d for d in list if num-d in list and num -d >= d]
print(list1)
print(len(list1))

集合生成式

d = dict(a=6, b=2, c=3, e=6)
print({i for i in range(10) if i%3==0})
print({i for k,i in d.items()  if i%3==0})

字典生成式

service = {
    'http': 80,
    'mysql': 3306,
    'ssh': 22
}
#需求一将所有key值变为大写
#利用列表生成器的方法
services = {k.upper():v for k,v in service.items()}
#大小写key值合并, 统一以小写key值输出
d = dict(a=1,b=2,c=3,A=1,B=4)
print({k.lower():d.get(k.lower(), 0)+d.get(k.upper(),0) for k,v in d.items()})
#  需求3: 把字典的key和value值调换;
d1 = {'name': 'fentiao', 'gender': 'male'}
print({v:k for k,v in d1.items()})

生成器

将列表生成式改为生成器
li = [i for i in range(100) if i%2==0]
# 生成器
g = (i for i in range(100) if i%2==0)
查看生成器的两种方法

在python3中用g.next()方法
在python2中用g.next()

print(g.__next__())
print(g.__next__())
print(g.__next__())
print(next(g))

生成器是可迭代的

可以通过这种方法查看
from collections import Iterable
print(isinstance(g, Iterable))
for 循环的底层原理
g = (i for i in range(3))
while True:
    try:  #异常处理器
        print(g.__next__())
    except:
        break
菲波拉契数列
def fib(num):  # num=5
    a, b, count = 0, 1, 1    # a=0, b=1
    while count <= num:
        yield b            # 1
        a, b = b, a + b     # a=1, b=1
        count += 1
g = fib(10)    #如果函数中有yield关键字,返回一个生成器对象,目前不执行函数内容
print(g.__next__()) #当遇到g.__next__()方法时执行函数,当遇到yield关键字是执行结束,print(g.__next__())的是yield后面的值
print(g.__next__()) #当再次调用g.__next__()方法时,函数接着上次停止的地方执行,遇到yield停止
print(g.__next__())
g.close  #关闭生成器

生成器的应用,迷你机器人的聊天

def chat_robot():
    res = ''
    while True:
        received = yield res
        if 'age' in received or "年龄" in received:
            res = "年龄保密!"
        elif 'name' in received or '姓名' in received:
            res = '我是小冰.....'
        elif 'money' in received or '钱' in received:
            res = '没钱....'
        else:
            res = '我不知道你在说什么, 请换种说法!'
def main():
    Robot = chat_robot()
    Robot.__next__()
    while True:
        send_data = input("粉条>>")
        if send_data == 'q' or send_data == 'qu`it':
            print("我也要休息了....")
            break
        robot_data = Robot.send(send_data)
        print("小冰>>", robot_data)
main()

高阶函数

map

m = map(mypower, [1,2,3])
#map是可迭代的
print(m,type(m),isinstance(m, Iterable))#<map object at 0x7fc5ab327240> <class 'map'> True
#想要打印map的内容,可以转换为列表打印出来
print(list(map(mypower, [1,2,3])))
#或者通过for循环
for i in m:
    print(i)
def fun(*num):
    return sum(num)
m = map(fun, [1, 2, 3], {5, 6, 7})
for i in m:
    print(i)

通过reduce实现磊加和阶乘

from functools import reduce #调用reduce模块
#累加
def add(x,y):
    return x+y
print(reduce(add,range(1,101)))
#阶乘
def e(x,y):
    return x*y
print(reduce(e,range(1,6)))

filter:过滤

print([i for i in [12,34,56,67]  if i%2==0]) #过滤出列表中的所有偶数

过滤函数的应用
删除1-100之间的质数

#首先找出1-100之间的所有质数
def is_prime(num):
    if num <= 0:
        return False
    elif num == 1 and num ==2:
        return True
    else:
        for i in range(2,num):
            if num%i == 0:
                return False
        else:
            return True
#判断这个是不是质数
def is_not_prime(num):
    return not is_prime(num)
#利用高阶函数过滤
print(list(filter(is_not_prime,range(1,101))))

sorted排序

用sort函数对列表排序时会影响列表本身,而sorted不会。

print(sorted([235,23,25,333])) #由小到大
print(sorted([235,23,25,333],reverse=True)) #反转由大到小
info = [
    ['001', 'apple', 1000, 2],
    ['002', 'xiaomi', 10, 2000],
    ['003', 'Oppo', 200, 1900],
    ['004', 'computer', 900, 5000]
]
#按price排序
def sorted_by_prince(info):
    return info[3]
print(sorted(info,key=sorted_by_prince))
info = {
    '001':{
        'name':'apple',
        'count':1000,
        'price':2
    },

    '002': {
        'name': 'xiaomi',
        'count': 10,
        'price': 2000
    },
    '003': {
        'name': 'Oppo',
        'count': 200,
        'price': 1900
    }
}
def sorted_by_price(num):
    return num['price']
print(sorted(info.values(),key=sorted_by_price))
print(sorted(info.values(),key=lambda num:num['price']))

sorted函数的应用,移动数组中的0,或者其他元素

n = int(input())
l = [int(input()) for i in range(n)]
def sort_by(num):
    if num == 0:
        return 1
    else:
        return 0
print(sorted(l,key=sort_by)) #将'0'放在最后
print(sorted(l,key=lambda num : 0 if num==0 else 1))#将0放在最前面

高阶函数的返回值是函数
闭包:函数里面嵌套函数,可以用于函数装饰器

def compare1(base):   # base=10
    def compare2(y):    # y = 3
        return base > y
    return compare2

装饰器

装饰器的第一种模版

import functools
def 装置启名称(fun):
    @functools.wraps(fun)
    def wrapper(*args,**kwargs):
        pass
    return wrapper
#使用装饰器  语法糖
@装饰器名称  #hello = 装饰器名称   hello = wrapper
def hello():
    pass
hello()   #实质上是执行wrapper函数

装饰器的应用

计算一个函数的执行时间

import time
def compute_time(fun):
#    @functools.wraps(fun)
    def wrapper():
        start_time = time.time()
        fun()
        end_time = time.time()
        print("%S函数执行的时间%ss",(fun.__name__,end_time-start_time))
    return wrapper
@compute_time
def hello():
    print("hello")
    time.sleep(1)
hello()

实现日志记录的装饰器

import functools
import time
import random
def info_log(fun):
    @functools.wraps(fun)
    def wrapper(*args): #*args,**kwargs代表可变参数和关键字参数,
        """
        this is a wrapper function add log
        """
        start_time = time.time()
        res = fun(*args) #*args,*kwargs代表对元组和字典进行解包
        end_time = time.time()
        print("%s %s 执行时间为%.2fs 执行结果%s" %(time.ctime(),fun.__name__,end_time-start_time,res))
        return res
    return wrapper
@info_log
def log(x,y):
    """
     add function
    :param x: num1 -> int
    :param y: num2 -> int
    :return:  num1+num2 -> int
    """
    time.sleep(random.random())  #随机生成一个0-1的数
    return x+y
log(1,2)
print(log.__name__)#打印函数名称
print(log.__doc__) #打印函数功能

装饰器的第二个模版

def decorator_a(func):  
    def inner_a(*args, **kwargs):
        print('Get in inner_a')
        return func(*args, **kwargs)  # f(1)
    return inner_a
def decorator_b(func):  # decorator_b(inner_a)
    def inner_b(*args, **kwargs):
        print('Get in inner_b')
        return func(*args, **kwargs)   # inner_a(1)
    return inner_b
# 当有多个装饰器时, 从下到上调用装饰器;
@decorator_b  # f = decorator_b(inner_a)   # f=inner_b
@decorator_a  # f = decorator_a(f)   f=inner_a
def f(x):
    print('Get in f')
    return x * 2
f(1)

在实际应用中,会使用多个装饰器,先判断是否登录成功,再判断权限是否够

import functools
def is_admin(fun):
    @functools.wraps(fun)
    def wrapper(*args,**kwargs):
        if kwargs['name']=='admin':
            fun(*args,**kwargs)
        else:
            print("no permission")
    return wrapper
login = ['root','westos','admin']
def is_login(fun):
    @functools.wraps(fun)
    def wrapper(*args,**kwargs):
        if kwargs['name'] in login:
            fun(*args,**kwargs)
        else:
            print("%s没有登录" %(kwargs['name']))
    return wrapper
@is_login
@is_admin
def bbs(name):
    print("bbs...")
bbs(name='admin')

匿名函数lambda

#利用匿名函数求1-100之间所有偶数的和
from functools import reduce
print(reduce(lambda x,y:x+y,range(2,101,2)))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值