第六章---python函数编程

🌞欢迎来到python的世界 
🌈博客主页:卿云阁

💌欢迎关注🎉点赞👍收藏⭐️留言📝

🌟本文由卿云阁原创!

🌠本阶段属于练气阶段,希望各位仙友顺利完成突破

📆首发时间:🌹2021年4月3日🌹

✉️希望可以和大家一起完成进阶之路!

🙏作者水平很有限,如果发现错误,请留言轰炸哦!万分感谢!


目录

        🍈 一、参数

🍉二. 返回值return

🍊三,变量的作用域

🍋四、内置函数

🍑五、匿名函数

🍒六、推导式

🥒七、迭代器

🥬八、生成器

🥦九、装饰器

🍈 参数

(1)形参与实参

def calc(x,y):
    res = x**y
    print(res)

a = 5
b = 4

calc(a,b)

 (2)默认参数

def zongce(name,mid,end,mid_rate=0.4):
    zongce=mid*mid_rate+end*(1-mid_rate)
    print("----学⽣信息------")
    print("期中成绩:", mid)
    print("期末成绩:", end)
    print("综测成绩:{0:<5}".format( zongce))
zongce("qingyun",98,99)
zongce("zhangxveqing",98,99,0.5)



结果
----学⽣信息------
期中成绩: 98
期末成绩: 99
综测成绩:98.6 
----学⽣信息------
期中成绩: 98
期末成绩: 99
综测成绩:98.5 

(3)可变参数

def sum(a,b,*c):
    print(c)
    total=a+b
    for i in c:
        total=total+i
    return total
print(sum(1,2,3,4,5,6,7))

结果
(3, 4, 5, 6, 7)
28

def sum(a,b,*c,**d):
    print(c)
    print(d)
    total=a+b
    for i in c:
        total=total+i
    for key in d:
        total=total+d[key]
    return total
print(sum(1,2,3,4,5,6,7,qingyun=1,zxq=2))
结果
(3, 4, 5, 6, 7)
{'qingyun': 1, 'zxq': 2}
31


 🍉返回值return

函数外部的代码要想获取函数的执⾏结果,就可以在函数⾥⽤ return 语句把结果返回
注意
函数在执⾏过程中只要遇到 return 语句,就会停⽌执⾏并返回结果, so 也可以理解为 return 语句 代表着函数的结束 如果未在函数中指定return, 那这个函数的返回值为 None
def zuowen(name,f,s,*o):
    max=f
    if f<s:
        max=s
    for i in o:
        if max<i:
            max=i
    print("----最终学⽣作文分数------")
    print("姓名:", name)
    print("作文分数:", max)
zuowen('qingyun',99,98,99,97,96,95)


结果
----最终学⽣作文分数------
姓名: qingyun
作文分数: 99

多条return语句

import math
def is_prime(n):
    if n<2: return False
    i=2
    while(i<math.sqrt(n)):
        if n%i==0:
           return False
        i+=1
    return True
for i in range(100):
    if is_prime(i):print(i,end=' ')
结果
2 3 4 5 7 9 11 13 17 19 23 25 29 31 37 41 43 47 49 53 59 61 67 71 73 79 83 89 97 

返回多个值

import random
def randomarry(n):
    a=[]
    for i in range(n):
        a.append(random.random())
    return a
b=randomarry(5)
print(b)
结果:
[0.6068501158240774, 0.0761204880150359, 0.8275832346568391, 0.3464213540970127, 0.8964706536915046]

🍊变量的作用域

name = "qingyun"
def change_name():
 name = "qingyunqingyunge"
 print("after change", name)
change_name()
print("now name",name)

传递列表、字典产⽣的现象
d = {"name":"qingyun","age":19,"hobbie":"pinpang"} 
l = ["Rebeeca","Katrina","Rachel"]
def change_data(info,girls):
 info["hobbie"] = "学习"
 girls.append("XiaoYun")
 
change_data(d,l)
print(d,l)


🍋内置函数

前面使用过一些函数,有的同学会疑问我没有导入这个函数,为什么可以直接使用?
因为这些函数都是一个叫做 builtins 模块中定义的函数,而 builtins 模块默认在Python环境启动的时 候就自动导入,所以你可以直接使用这些函数。
abs()
绝对值函数。如abs(-1)= 1
print(abs(-10))
f = abs 
print(f(-1))
abs=id 
print(abs(1))

以abs()函数为例,展示两个特性。一是,内置函数是可以被赋值给其他变量的,同样也可以将其他对象赋 值给内置函数,这时就完全变了。所以,内置函数不是Python关键字,要注意对它们的保护,不要使用和 内置函数重名的变量名,这会让代码混乱,容易发生难以排查的错误。

all()

 接收一个可迭代对象,如果对象里的所有元素的bool运算值都是True,那么返回True,否则False

print(all([1,1,1]))

结果:
True
any()
接收一个可迭代对象,如果迭代对象里有一个元素的bool运算值是True,那么返回True,否则False。与all()是一 对兄弟。
print(any([0,0,1]))

结果
True
bin()、oct()、hex()
三个函数是将十进制数分别转换为2/8/16进制
i = 10 
print(bin(i))

结果
0b1010

zip()

组合对象。将对象逐一配对。

   等等 


🍐range函数

a = ['Google', 'Baidu', 'Huawei', 'Taobao', 'QQ']
for i in range(len(a)):
    print(i, a[i])
    
结果
0 Google
1 Baidu
2 Huawei
3 Taobao
4 QQ


🍑匿名函数

当我们在创建函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。这省去了我们挖空心思为 函数命名的麻烦,也能少写不少代码,很多编程语言都提供这一特性。
Python语言使用 lambda 关键字来创建匿名函数。
所谓匿名,即不再使用 def 语句这样标准的形式定义一个函数。
1. lambda只是一个表达式,而不是一个代码块,函数体比def简单很多。
2. 仅仅能在lambda表达式中封装有限的逻辑。
3. lambda 函数拥有自己的命名空间
lambda x: x * x
它相当于下面的函数
def f(x): 
    return x*x 
关键字lambda表示匿名函数,冒号前面的x表示函数参数,x*x是执行代码
匿名函数只能有一个表达式,不用也不能写return语句,表达式的结果就是其返回值。 匿名函数没有函数名字, 不必担心函数名冲突,节省字义空间。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量, 再利用变量来调用该函数.
f = lambda x: x * x
print(f(6))
#也可以把匿名函数作为别的函数的返回值返回 
def count(i,j): 
    return lambda : i*j
f = count(6,7) 
print(f)
print(f())

 匿名函数的应用

对列表中的字典进行排序
lis = [1,-2,4,-3]
lis.sort(key=abs)
print(lis)
infors = [{'name':'cangls','age':18},{'name':'bols','age':20},{'name':'jtls','age':25}]
infors.sort(key = lambda x:x['name'])
print(infors)

匿名函数当做实参
def test(a,b,func): 
    result = func(a,b) 
    return result 
nums = test(11,22,lambda x,y:x+y) 
print(nums)


🍒推导式

Python语言有一种独特的推导式语法,相当于语法糖的存在,可以帮你在某些场合写出比较精简酷炫的代码。
列表推导式
lis = [x * x for x in range(1, 10)] 
print(lis)

字典推导式  

dic = {i:i**3 for i in range(5)} 
print(dic)

集合推导式  

s = {i for i in 'abasrdfsdfa' if i not in 'abc'} 
print(s)
#把abc排除剩余字符串


🥒迭代器

在介绍迭代器之前,先说明下迭代的概念:
迭代:通过for循环遍历对象的每一个元素的过程。
Python的for语法功能非常强大,可以遍历任何可迭代的对象。
在Python中, list/tuple/string/dict/set/bytes 都是可以迭代的数据类型。
可以通过collections模块的 Iterable 类型来判断一个对象是否可迭代:
from collections import Iterable 
isinstance('abc', Iterable) # str是否可迭代 
True 
isinstance([1,2,3], Iterable) # list是否可迭代 
True 
isinstance(123, Iterable) # 整数是否可迭代 
False
迭代器是一种可以被遍历的对象,并且能作用于next()函数。迭代器对象从集合的第一个元素开始访问,直到所 有的元素被访问完结束。 迭代器只能往后遍历不能回溯,不像列表,你随时可以取后面的数据,也可以返回头取 前面的数据。迭代器通常要实现两个基本的方法: iter() next() 字符串,列表或元组对象,甚至自定义对象都可用于创建迭代器:
from collections.abc import Iterable,Iterator
print(isinstance([],Iterable)) #是否可迭代
print(isinstance([],Iterator)) #是否是迭代器
lis=[1,2,3,4]
it = iter(lis) # 使用Python内置的iter()方法创建迭代器对象
print(next(it)) # 使用next()方法获取迭代器的下一个元素
print(next(it)) # 使用next()方法获取迭代器的下一个元素
print(next(it)) # 使用next()方法获取迭代器的下一个元素
print(next(it))# 使用next()方法获取迭代器的下一个元素

结果
True
False
1
2
3
4

Python的迭代器表示的是一个元素流,可以被next()函数调用并不断返回下一个元素,直到没有元素时抛 出StopIteration错误。可以把这个元素流看做是一个有序序列,但却不能提前知道序列的长度,只能不断通过 next()函数得到下一个元素,所以迭代器可以节省内存和空间。 迭代器(Iterator)和可迭代(Iterable)的区别:
1. 凡是可作用于for循环的对象都是可迭代类型;
2. 凡是可作用于next()函数的对象都是迭代器类型;
3. list、dict、str等是可迭代的但不是迭代器,因为next()函数无法调用它们。可以通过iter()函数将它们转换成 迭代器。
4. Python的for循环本质上就是通过不断调用next()函数实现的。

🥬生成器

有时候,序列或集合内的元素的个数非常巨大,如果全制造出来并放入内存,对计算机的压力是非常大的。比 如,假设需要获取一个10**20次方如此巨大的数据序列,把每一个数都生成出来,并放在一个内存的列表内,这 是粗暴的方式,有如此大的内存么?如果元素可以按照某种算法推算出来,需要就计算到哪个,就可以在循环的 过程中不断推算出后续的元素,而不必创建完整的元素集合,从而节省大量的空间。在Python中,这种一边循环
一边计算出元素的机制,称为生成器:generator。
生成生成器:
g = (x * x for x in range(1, 4))
print(g)

可以通过next()获得generator的下一个返回值,这点和迭代器非常相似:  

g = (x * x for x in range(1, 4))
print(g)
print(next(g))
print(next(g))

结果:
1
4

除了使用生成器推导式,我们还可以使用 yield 关键字。

def createNums():
     print("----func start------")
     a,b = 0,1
     for i in range(5):
         print(b)
         print("--1--")
         yield b
         print("--2--")
         a,b = b,a+b # a,b = 1, 1 a,b = 1,2
         print("--3--")
         print("----func end------")
g= createNums()
print(next(g)) # 如果想得到yield的值,可以打印next(g)
print(next(g)) 
结果
----func start------
1
--1--
1
--2--
--3--
----func end------
1
--1--
1

在 Python中,使用yield返回的函数会变成一个生成器(generator)。 在调用生成器的过程中,每次遇到yield 时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次执行next()方法时从当前位置继续运行。
生成器的应用
实现多任务
def test1():
     while True:
          print("--1--")
          yield None
def test2():
     while True:
          print("--2--")
          yield None
t1 = test1()
t2 = test2()
while True:
     next(t1)
     next(t2)
     break
结果
--1--
--2--

🥦装饰器

       装饰器(Decorator):从字面上理解,就是装饰对象的器件。可以在不修改原有代码的情况下,为被装饰的对 象增加新的功能或者附加限制条件或者帮助输出。装饰器有很多种,有函数的装饰器,也有类的装饰器。装饰器 在很多语言中的名字也不尽相同,它体现的是设计模式中的装饰模式,强调的是开放封闭原则。装饰器的语法是 将@装饰器名,放在被装饰对象上面。
@dec 
def func(): 
   pass
在介绍装饰器之前,先要了解几个知识点
重名函数会怎么样?
def test():
     print('1')
def test():
     print('2')
test() #这个时候会输出什么? 会输出2,后面的会覆盖前面的函数 
接下来就是一个比较经典的案例了,有一个大公司,下属的基础平台部负责内部应用程序及API的开发。另外还 有上百个业务部门负责不同的业务,这些业务部门各自调用基础平台部提供的不同函数,也就是API处理自己的业务,情况如下:
基础平台部门提供的功能如下
def f1(): 
    print("业务部门1的数据接口......") 
def f2(): 
    print("业务部门2的数据接口......") 
def f3(): 
    print("业务部门3的数据接口......") 
def f100(): 
    print("业务部门100的数据接口......") 
#各部门分别调用基础平台提供的功能 
f1() 
f2() 
f3() 
f100()
目前公司发展壮大,但是以前没有考虑到验证相关的问题,即:基础平台提供的功能可以被任何人使用。现在需 要对基础平台的所有功能进行重构,为平台提供的功能添加验证机制,执行功能前,先进行验证 老大把工作交给 A,他是这么做的: 跟每个业务部门交涉,每个业务部门自己写代码,调用基础平台的功能之前先验证。这样一
来基础平台就不需要做任何修改了。 当前A被老大开除了 老大又把工作交给B,他是这么做的:
def f1(): 
# 验证1 
# 验证2 
# 验证3 
def f2(): 
# 验证1 
# 验证2 
# 验证3 
过了一周B也被开除了。。。。。。。。。。
老大又把工作交给C,他是这么做的:
def check_login() 
# 验证1
 # 验证2
 # 验证3 
def f1(): 
    check_login() 
def f2(): 
    check_login()
老大说写代码要遵循开放封闭的原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,已经实现的功能不允许修改,但可以被扩展 。
封闭:已实现的功能代码块
开放:对扩展开发
老大给出了方案, 
def foo(): 
    def inner(): 
        验证1 
        验证2 
        验证3 
        result = func() 
        return result
return inner 

@foo 
def f1(): 
    pass
@foo
def f2(): 
    pass
看不懂?没关系,接下来写一个简单点的
def w1(func):
     def inner():
          print('正在验证权限')
          func()
     return inner
def f1():
     print('f1')

innerFunc = w1(f1) # innerFunc = inner
innerFunc() # inner()
f1 = w1(f1)
f1()
def outer(func):
     def inner():
          print("认证成功!")
          result = func()
          print("日志添加成功")
     return inner
@outer # f1 = outer(f1) = inner
def f1():
     print("业务部门1数据接口......")
f1()

结果:
正在验证权限
f1
正在验证权限
f1
认证成功!
业务部门1数据接口......
日志添加成功
1 程序开始运行,从上往下解释,读到def outer(func):的时候,发现这是个“一等公民”函数,于是把 函数体加载到内存里,然后过。
 2 读到@outer的时候,程序被@这个语法糖吸引住了,知道这是个装饰器,按规矩要立即执行的,于是程序 开始运行@后面那个名字outer所定义的函数。
 3 程序返回到outer函数,开始执行装饰器的语法规则。 规则是:被装饰的函数的名字会被当作参数传递给装饰函数。装饰函数执行它自己内部的代码后,会将它的 返回值赋值给被装饰的函数。原来的f1函数被当做参数传递给了func,而f1这个函数名之后会指向inner 函数

例子:

import time
def login():
  start = time.time()
  print("用户准备登录")
  time.sleep(3)
  print("用户登录成功")
  end = time.time()
  print(f"消耗时间:{(end-start):.2f}S")
login()

import time
def login():
  print("用户准备登录")
  time.sleep(3)
  print("用户登录成功")

start = time.time()
login()
end = time.time()
print(f"消耗时间:{(end - start):.2f}S")

             

import time
def login():
  print("用户准备登录")
  time.sleep(3)
  print("用户登录成功")
def cal_time(fn):
    def wrapper(*args, **kwargs):
        start = time.time()
        res = fn(*args, **kwargs)
        end = time.time()
        print(f"消耗时间:{(end - start):.2f}S")
        return res
    return wrapper
w = cal_time(login)
w()

import time
def cal_time(fn):
    def wrapper(*args, **kwargs):
        start = time.time()
        res = fn(*args, **kwargs)
        end = time.time()
        print(f"消耗时间:{(end - start):.2f}S")
        return res
    return wrapper
@cal_time
def login():
  print("用户准备登录")
  time.sleep(3)
  print("用户登录成功")

login()


🥦函数闭包

       开发应用软件时,功能点非常多,导致多个开发人员可能会在同一个文件中拥有自己开发功能 的代码。

#开发人员A: 聊天功能
msg = "需要发送的消息"
timeline = "聊天时长统计"

#开发人员B: 视频功能
data = "传递的视频数据"
timeline = "视频时长统计"

print(data)
print(timeline)

      上述代码中,两个开发人员开放的不同功能中,使用了相同名称的变量,就会导致数据互相覆盖,导致业务流程收到影响(刚视频1分钟,提示已经视频2小时请休息一下)。

解决方案:

       每个功能都使用一个独立的函数进行封装,将自己的代码(不论是变量、函数)全部都封装在一个大函数中,通过函数与函数之间的隔离性,完成不同功能之间的代码隔离,避免冲突。这样的操作方式称为闭包。

def developer_a():
    # 开发人员A: 聊天功能
    msg = "需要发送的消息"
    timeline = "聊天时长统计"
    def chat():
        print("正在聊天中")
        print(f"发送消息:{msg}")
        print(f"聊天时长:{timeline}")
    chat()
def developer_b():
    #开发人员B: 视频功能
    data = "传递的视频数据"
    timeline = "视频时长统计"
    def video():
        print("正在视频中")
        print(f"发送视频数据:{data}")
        print(f"视频时长:{timeline}")
    video()
developer_a()
developer_b()

          声明在内部的一个函数,使用了外部函数的局部变量,这样的操作语法称为闭包。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
以下是使用回溯法实现0-1背包问题的Python代码: ```python def knapsack(weights, values, capacity): """ :param weights: 物品重量列表 :param values: 物品价值列表 :param capacity: 背包容量 :return: 最大价值和 """ def backtrack(i, cw, cv): nonlocal max_value if i == n or cw == capacity: max_value = max(max_value, cv) return # 选择不装第i个物品 backtrack(i + 1, cw, cv) # 选择装第i个物品 if cw + weights[i] <= capacity: backtrack(i + 1, cw + weights[i], cv + values[i]) n = len(weights) max_value = 0 backtrack(0, 0, 0) return max_value ``` 使用示例: ```python weights = [2, 2, 4, 6, 3] values = [3, 4, 8, 9, 6] capacity = 9 max_value = knapsack(weights, values, capacity) print(max_value) # 输出 18 ``` 上述代码中,`backtrack` 函数是回溯函数,它的三个参数分别是:当前考虑到的物品下标 `i`,当前背包的重量 `cw` 和当前背包的价值 `cv`。在回溯函数中,我们首先选择不装第 `i` 个物品,然后选择装第 `i` 个物品(当且仅当当前背包容量可以容纳第 `i` 个物品时才选择装)。在回溯过程中,我们不断更新最大价值和 `max_value`。回溯结束后,`max_value` 即为最大价值和。 在本题中,由于每个物品只有装或者不装两种选择,因此回溯树的每个节点的度数都为2,回溯树的深度为物品的个数 `n`。因此,回溯法的时间复杂度为 $O(2^n)$,不过实际上由于我们使用了剪枝(即当当前背包容量达到背包容量上限时不再继续搜索),因此实际运行的时间要小于 $O(2^n)$。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卿云阁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值