函数进阶知识整理

闭包函数

把函数A和变量x包在函数B内部,然后通过函数B的返回值返回出函数A对象

def outter(x):
    x = 1

    def inner():
        print(x)
    return inner

f = outter(1)
f()
f()
f()
# 查看闭包的元素
print(F"f.__closure__[0].cell_contents: {f.__closure__[0].cell_contents}")
1
1
1
f.__closure__[0].cell_contents: 1

装饰器

用来给函数加功能的,他的本质也是函数

为什么用装饰器

假设我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能是开放的。

注意:

  1. 不改变被装饰函数的源代码
  2. 不改变被装饰函数的调用方式

装饰器语法糖

**在被装饰函数正上方,并且是单独一行写上@装饰器名**</font>(用法)

装饰器模板

def outter(func):
    def wrapper(*args,**kwrags):
        # 逻辑
        res = func(*args,**kwargs)  # func是被装饰的函数
        return res
    return wrapper

@outter
def index():
    pass   

# 三层装饰器模板
def sanceng(engine):
    def outter(func):
        def wrapper(*args,**kwrags):
            # 逻辑
            res = func(*args,**kwargs)  # func是被装饰的函数
            return res
        return wrapper
    return outter

@sanceng(engine)
def index():
    pass

迭代器

迭代器即迭代的工具,那什么是迭代呢?`
迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值

为何要有迭代器

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

可迭代对象: 具有iter方法的对象, 可迭代对象不一定是迭代器对象`

迭代器对象: 具有iter和next方法的对象, 迭代器对象一定是可迭代对象, 迭代器对象加上iter方法还是迭代器本身`

#优点:
  - 提供一种统一的、不依赖于索引的迭代方式
  - 惰性计算,节省内存
#缺点:
  - 无法获取长度(只有在next完毕才知道到底有几个值)
  - 一次性的,只能往后走,不能往前退

for循环称为迭代器循环,in后必须是可迭代的对象。

lis = [1, 2, 3]
for i in lis:
    print(i)

三元表达式

x = 10
y = 20
print(x if x > y else y)

x > y 条件成立时返回x值,不成立返回y值

列表推导式

print(F"[i for i in range(10)]: {[i for i in range(10)]}")

print(F"[i**2 for i in range(10)]: {[i**2 for i in range(10)]}")
[i for i in range(10)]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

[i**2 for i in range(10)]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

字典生成式

print({i: i**2 for i in range(10)})
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

生成器

只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,并且不会执行函数内部代码

生成器的本质就是迭代器,同时也并不仅仅是迭代器,不过迭代器之外的用途实在是不多,所以我们可以大声地说:生成器提供了非常方便的自定义迭代器的途径。

yield关键字

yield的英文单词意思是生产,在函数中但凡出现yield关键字,再调用函数,就不会继续执行函数体代码,而是会返回一个值。

yield和return:

  1. 相同点:两者都是在函数内部使用,都可以返回值,并且返回值没有类型和个数的限制
  2. 不同点:return只能返回一次值,终止函数;yield可以返回多次值,暂停函数,遇到下一个yield继续运行函数体代码

生成器表达式

  • 把列表推导式的[]换成()就是生成器表达式
  • 优点:省内存,一次只产生一个值在内存中

列表推导式相当于直接给你一筐蛋,而生成器表达式相当于给你一只老母鸡。

# 生成器表达式
with open('52.txt', 'r', encoding='utf8') as f:
    nums = [len(line) for line in f]

print(max(nums))

# 列表推导式
with open('52.txt','r',encoding='utf8') as f:
    nums = (len(line) for line in f)

print(max(nums)) # ValueError: I/O operation on closed file.

递归

函数调用函数本身,但是必须得有结束条件

递归必须要有两个明确的阶段:

  1. 递推:一层一层递归调用下去,进入下一层递归的问题规模都将会减小
  2. 回溯:递归必须要有一个明确的结束条件,在满足该条件开始一层一层回溯。

递归的精髓在于通过不断地重复逼近一个最终的结果。

匿名函数

没有名字的函数 lambda 参数:代码块

一般不单独使用,与 max/min/map/filter/sorted联用

内置函数

内置函数是直接用的,属于python解释器的

数据类型的内置函数只有数据类型本身才能使用

掌握:

1.bytes() #解码字符

res = '你好'.encode('utf8')  #encode转化为二进制,decode反转
print(res)

b'\xe4\xbd\xa0\xe5\xa5\xbd'

res = bytes('你好', encoding='utf8')
print(res)

b'\xe4\xbd\xa0\xe5\xa5\xbd'

2.chr()/ord() #chr()参考ASCII码表将数字转成对应字符;ord()将字符转换成对应的数字。

print(chr(65))
A
print(ord('A'))
65

3.divmod() #函数把除数和余数运算结果结合起来。

print(divmod(7, 2))
(3, 1)
print(divmod(8, 2))
(4, 0)
print(divmod(1+2j,1+0.5j))
((1+0j), 1.5j)

4.enumerate() #带有索引的迭代

l = ['a', 'b', 'c']
for i in enumerate(l):
    print(i)
(0, 'a')
(1, 'b')
(2, 'c')

5.eval() #eval 可以把 list, tuple, dict 转换成str,返回来也成立;即互转。

 # 字符串转成列表
 s = '[[1,2,],[3,4,],[5,6,],[8,9]]'
 li = eval(s)
 print(li)
 print(type(s))
 print(type(li))

 [[1, 2], [3, 4], [5, 6], [8, 9]]
 <class 'str'>
 <class 'list'>

 #字符串转成字典
 s = "{1:'a',2:'b'}"
 dic = eval(s)
 print(dic)
 print(type(s))
 print(type(dic))

 {1: 'a', 2: 'b'}
 <class 'str'>
 <class 'dict'>

 #字符串转成元组
 s = '([1,2,],(3,4,),[5,6,],(8,9))'
 tu = eval(s)
 print(tu)
 print(type(s))
 print(type(tu))

 ([1, 2], (3, 4), [5, 6], (8, 9))
 <class 'str'>
 <class 'tuple'>

6.hash() #获取取一个对象(字符串或者数值等)的哈希值。

print(hash('test'))#字符串
print(hash(1))#数字
print(hash(str([1, 2, 3])))#集合
print(hash(str(sorted({'1': 1}))))#字典

3354089792780274255
1
-2610670198615689204
-1768722922849136370

了解;

  1. abs #求绝对值。
  2. all #可迭代对象内元素全为真,则返回真。False : 0、空、None、False
  3. any #可迭代对象中有一元素为真,则为真。False : 0、空、None、False
  4. bin/oct/hex #二进制、八进制、十六进制转换。
  5. dir #函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。
  6. frozenset #返回一个冻结的集合,冻结后集合不能再添加或删除任何元素。
  7. gloabals/locals #函数会以字典类型返回当前位置的全部全局变量;函数会以字典类型返回当前位置的全部局部变量。
  8. pow
  9. round
  10. slice
  11. sum
  12. import

面向对象编程

面向过程编程是解决问题的一种思想,基于该思想编写程序就好比在设计一条流水线,面向对称编程其实是一种机械式的思维方式。

  • 优点: 思路清晰
  • 缺点: 可扩展性差 ; 功能与功能之间不独立 ; 调试麻烦

原文地址:https://www.cnblogs.com/asyouwish/p/11650683.html

时间: 2024-11-01 11:19:29

函数进阶知识整理的相关文章

python 函数基础知识整理

一.函数的定义: 定义:def 关键词开头,空格之后接函数名称和圆括号(),最后还有一个":". def 是固定的,不能变,必须是连续的def三个字母,不能分开... 空格 为了将def关键字和函数名分开 函数名:必须由字母下划线数字组成,不能是关键字,不能是数字开头,函数名还是要有一定的意义能够简单说明函数的功能 括号:是必须加的 注释:每一个函数都应该对功能和参数进行相应的说明,应该写在函数下面第一行.以增强代码的可读性. 调用:就是 函数名() 要记得加上括号 def 函数名(参

Linux动态库相关知识整理

动态库和静态库在C/C++开发中很常见,相比静态库直接被编译到可执行程序, 动态库运行时加载使得可执行程序的体积更小,更新动态库可以不用重新编译可执 行程序等诸多好处.作者是一个Linux后台开发,这些知识经常用到,所以 整理了一下这方面的知识.静态库相对简单,本文只关心Linux平台下的动态库. 创建动态库 这里我把一个短小却很有用的哈希函数编译成动态库做为示例,ELFhash用于对字符串做哈希,返回一个无符号整数. //elfhash.h #include <stdio.h> unsign

Python学习之旅—面向对象进阶知识:类的命名空间,类的组合与继承

前言 上篇博客笔者带领大家初步梳理了Python面向对象的基础知识,本篇博客将专注于解决三个知识点:类的命名空间,类的组合以及面向对象的三大特性之一继承,一起跟随笔者老看看今天的内容吧. 1.类的命名空间 在上一篇博客中,我们提到过对象可以动态添加属性,一起来回忆下昨天的知识点,看如下的代码: class A: pass a = A() a.name = 'alex' print(a.name) 这里我们手动为a对象添加了一个属性name,然后直接打印可以得到a对象的名称.通过这个例子,我们可以

Spring实战3:装配bean的进阶知识

主要内容: Environments and profiles Conditional bean declaration 处理自动装配的歧义 bean的作用域 The Spring Expression Language 在装配bean—依赖注入的本质一文中,我们探讨了Spring的三种管理bean的方式:自动装配.基于JavaConfig.基于XML文件.这篇文字将探讨一些Spring中关于bean的管理的高级知识,这些技能你可能不会每天都用,但是非常重要. 3.1 Environments

Linux进程管理知识整理

Linux进程管理知识整理 1.进程有哪些状态?什么是进程的可中断等待状态?进程退出后为什么要等待调度器删除其task_struct结构?进程的退出状态有哪些? TASK_RUNNING(可运行状态) TASK_INTERRUPTIBLE(可中断等待状态) TASK_UNINTERRUPTIBLE(不可中断等待状态) TASK_STOPPED(进程被其它进程设置为暂停状态) TASK_TRACED(进程被调试器设置为暂停状态) TASK_DEAD(退出状态) 进程由于所需资源得不到满足,从而进入

JAVA基础知识整理

一.首先先明白get与post的基本定义和区别: 这是两种在客户端和服务器端进行请求-响应的方法. 1get:从指定的资源请求数据. 2post:向指定的资源提交要处理的数据. get基本上用于从服务器取回数据,注意:get方法可能返回缓存数据. post可以从服务器上获取数据,不过,post方法不会缓存数据,并且常用语连同请求一起发送数据. 二. Jquery $.get()方法. $.get()方法通过Http Get发起请求,从服务器上请求数据. 语法:&.get(URL,callback

js事件(Event)知识整理

事件(Event)知识整理,本文由网上资料整理而来,需要的朋友可以参考下 鼠标事件 鼠标移动到目标元素上的那一刻,首先触发mouseover 之后如果光标继续在元素上移动,则不断触发mousemove 如果按下鼠标上的设备(左键,右键,滚轮--),则触发mousedown 当设备弹起的时候触发mouseup 目标元素的滚动条发生移动时(滚动滚轮/拖动滚动条..)触发scroll 滚动滚轮触发mousewheel,这个要区别于scroll 鼠标移出元素的那一刻,触发mouseout 事件注册 平常

【转载】UML类图知识整理

原文:UML类图知识整理 UML类图 UML,进阶必备专业技能,看不懂UML就会看不懂那些优秀的资料. 这里简单整理 类之间的关系 泛化关系(generalization) 泛化(generalize): 一条带空心箭头的线表示 实现(realize) : 一条带空心箭头的虚线表示 泛化在Java中表现为继承(extends) ,is-a的关系 实现在Android中表现为implements 接口,或者extends抽象类 依赖关系(dependency) 用一条带箭头的虚线表示:箭头的指向为

requirejs入门知识整理

使用模块化开发处理的三大问题: 1.命名冲突:2.繁琐的文件依赖 3.实现异步非阻塞的文件加载,避免网页失去响应 模块化的设计使得JavaScript代码在需要访问“全局变量”的时候,都可以通过依赖关系,把这些“全局变量”作为参数传递到模块的实现体里,在实现中就避免了访问或者声明全局的变量或者函数,有效的避免大量而且复杂的命名空间管理. requirejs以一个相对于baseUrl的地址来加载所有的代码.如果用了data-main属性,则该路径就是baseUrl,baseUrl亦可通过requi