python零散笔记

 

一、 函数闭包:

闭包,又称闭包函数或者闭合函数,其实和前面讲的嵌套函数类似,不同之处在于,闭包中外部函数返回的不是一个具体的值,而是一个函数。一般情况下,返回的函数会赋值给一个变量,这个变量可以在后面被继续执行调用。

例如,计算一个数的 n 次幂,用闭包可以写成下面的代码:

#闭包函数,其中 exponent 称为自由变量
def nth_power(exponent):
   def exponent_of(base):
       return base ** exponent
   return exponent_of # 返回值是 exponent_of 函数
square = nth_power(2) # 计算一个数的平方
cube = nth_power(3) # 计算一个数的立方

print(square(2))  # 计算 2 的平方
print(cube(2)) # 计算 2 的立方

运行结果为:

4 8

在上面程序中,外部函数 nth_power() 的返回值是函数 exponent_of(),而不是一个具体的数值。

需要注意的是,在执行完 square = nth_power(2) 和 cube = nth_power(3) 后,外部函数 nth_power() 的参数 exponent 会和内部函数 exponent_of 一起赋值给 square 和 cube,这样在之后调用 square(2) 或者 cube(2) 时,程序就能顺利地输出结果,而不会报错说参数 exponent 没有定义。

 

 

二、 匿名函数

lambda 只是一个表达式,函数体比 def 简单很多。 lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。 lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。 lambda 函数的语法只包含一个语句,如下:

lambda [arg1 [,arg2,.....argn]]:expression
#lambda 参数列表:return [表达式] 变量
#由于lambda返回的是函数对象(构建的是一个函数对象),所以需要定义一个变量去接收


# 可写函数说明,举例
sum = lambda arg1, arg2: arg1 + arg2;
# 调用sum函数
print ("相加后的值为 : ", sum( 10, 20 )) # 相加后的值为 : 30
print ("相加后的值为 : ", sum( 20, 20 )) # 相加后的值为 : 40

 

三、 生成器函数

生成器是Python中的一个对象,对这个对象进行操作,可以依次生产出按生成器内部运算产生的数据。但是要注意,如果不对生成器进行操作,是不会产生数据的。称这样的方式为惰性求值,延或者迟求值。

生成器函数,就是说定义函数时,内部带yield就算生成器函数。

每次返回的值就是yield后面的值,这个yield很牛逼,和return一样,遇到之后就返回后面的值,但是yield会记住当时执行到哪里了,下一次执行从这个地方开始(就是生成器的特点)。

def g2():
   for x in range(5):
       yield x*2

list(g2)
[0, 2, 4, 6, 8]

就是yield from 语法,一种看起来简洁的表达形式吧。

普通形式的生成器函数:

def inc1():
  for x in range(10000):
      yield x

相当于

def inc2():
  yield from range(10000)

也就是说,yield from iterable 相当于 yield item for item in iterable。

 

 

四、 函数装饰器

  • 函数可以被赋值给其他变量

  • 函数可以被删除

  • 可以在函数里面再定义函数,函数嵌套。

  • 函数可以作为参数传递给另外一个函数

  • 函数可以作为另一个函数的返回值

    def makeitalic(fun):
             def wrapped():
                       return "<i>" + fun() + "</i>"
             return wrapped

    def hello():
             return "hello world"

    hello = makeitalic(hello)
    print(hello()) #<i>hello world
    #makeitalic就是一个装饰器(decorator),它封装了原函数hello,并返回了一个新函数,用于增强原函数的功能,并将其赋值给hello。
    #一般情况下,我们使用装饰器提供的@语法糖(Syntactic Sugar),来简化上面的操作。

    def makeitalic(fun):
       def wrapped():
           return "<i>" + fun() + "</i>"
       return wrapped
    @makeitalic
    def hello():
       return "hello world"
    print(hello()) #<i>hello world

     

 

五、 正则表达式

使用正则表达式步骤

1、寻找规律;

2、使用正则符号表示规律;

3、提取信息,如果每一个字符都能匹配,则匹配成功;一旦有匹配不成功的字符则匹配失败。

正则表达式中常见的基本符号

1.点号“.”

一个点号可以代替除了换行符(\n)以外的任何一个字符,包括但不限于英文字母、数字、汉字、英文标点符号和中文标点符号。

2.星号“*”

一个星号可以表示它前面的一个子表达式(普通字符、另一个或几个正则表达式符号)0次到无限次。

3.问号“?”

问号表示它前面的子表达式0次或者1次。注意,这里的问号是英文问号。

4.反斜杠“\”

反斜杠在正则表达式里面不能单独使用,甚至在整个Python里都不能单独使用。反斜杠需要和其他的字符配合使用来把特殊符号变成普通符号,把普通符号变成特殊符号。如:“\n”。

5.数字“\d”

正则表达式里面使用“\d”来表示一位数字。再次强调一下,“\d”虽然是由反斜杠和字母d构成的,但是要把“\d”看成一个正则表达式符号整体。

6.小括号“()”

小括号可以把括号里面的内容提取出来。

常见的正则表达式举例

  1. .*?(匹配所有内容)

例如:'<title>(.*?)</title>' 将网页的标题爬取下来。

2、\w 单词字符[A-Z a-z 0-9_], "+" 匹配前一个字符1次或无限次 例如:一个人的邮箱是这样的lixiaomei@qq.com,那么我们如何从一大堆的字符串把它提取出来呢?

pattern: \w+@\w+.com

思考:若邮箱为hello123@heuet.edu.com,如何匹配?

pattern:\w+@(\w+.)?\w+.com ?代表了匹配0次或者1次括号分组内的匹配内容,"()"则表示被括内容是一个分组,分组序号从pattern字符串起始往后依次排列。因为是匹配0次或1次,那么就意味着括号内的部分是可有可无的,所以这个pattern就可能匹配以上两种邮箱格式。

扩展: \w+@(\w+.)*\w+.com 模式就更厉害了," * " 可以匹配0次或无限次。

re库的核心函数

 

 

 

1、compile()函数 (可有可无)

• 函数定义: compile(pattern, flag=0)

• 函数描述:编译正则表达式pattern,然后返回一个正则表达式对象。

为什么要对pattern进行编译呢?《Python核心编程》里面是这样解释的:

使用预编译的代码对象比直接使用字符串要快,因为解释器在执行字符串形式的代码前都必须把字符串编译成代码对象。

2、match()函数

函数定义: match(pattern, string, flag=0)

函数描述:只从字符串的最开始与pattern进行匹配,匹配成功返回匹配对象(只有一个结果),否则返回None。

3、search()函数

函数定义: search(pattern, string, flag=0) 函数描述:与match()工作的方式一样,但是search()不是从最开始匹配的,而是从任意位置查找第一次匹配的内容。如果所有的字串都没有匹配成功,返回None,否则返回匹配对象。

4、findall()函数

函数定义: findall(pattern, string [,flags]) 函数描述:查找字符串中所有出现的正则表达式模式,并返回一个匹配列表

上面同时列出了match、search、findall三个函数用法。findall与match和search不同的地方是它会返回一个所有无重复匹配的列表。如果没找到匹配部分,就返回一个空列表。

匹配对象的方法(提取)

以上re模块函数的返回内容可以分为两种:

返回匹配对象:就是上面如 <_sre.SRE_Match object; span=(0, 5), match='12345'>这样的对象,可返回匹配对象的函数有match、search、finditer。
返回一个匹配的列表:返回列表的就是 findall。

因此匹配对象的方法只适用match、search、finditer,而不适用与findall。

常用的匹配对象方法有这两个:group、groups、还有几个关于位置的如 start、end、span就在代码里描述了。

1、group方法

方法定义:group(num=0) 方法描述:返回整个的匹配对象,或者特殊编号的字组

再看下面的实例:

这里就需要用到我们之前提到的分组概念。

分组的意义在于:我们不仅仅想得到匹配的整个字符串,我们还想得到整个字符串里面的特定子字符串。如上例中,整个字符串是“我12345+abcde”,但是想得到 “abcde”,我们就可以用()括起来。因此,你可以对pattern进行任何的分组,提取你想得到的内容。

2、groups方法

方法定义:groups(default =None) 方法描述:返回一个含有所有匹配子组的元组,匹配失败则返回空元组

re模块的属性(flag)

re模块的常用属性有以下几个:

re.I: 匹配不分大小写;(常用) re.L: 根据使用的本地语言环境通过\w, \W, \b, \B, \s, \S实现匹配; re.M: ^和$分别匹配目标字符串中行的起始和结尾,而不是严格匹配整个字符串本身的起始和结尾; re.S: “.”(点号)通常匹配除了\n(换行符)之外的所有单个字符,该标记表示“.”(点号)能够匹配全部字符;(常用) re.X: 通过反斜线转义,否则所有空格加上#(以及在该行中所有后续文字)都被忽略,除非在一个字符类中或者允许注释并且提高可读性;

注意:

  • 如果我们定义了compile编译,需要先将flag填到compile函数中,否则填到匹配函数中会报错; 如果没有定义compile,则可以直接在匹配函数findall中填写flag。

附录:正则表达式中语法一览表

六、 文件I/O

文件读取与操作

open函数

open()

函数用于创建或打开指定文件,该函数的常用语法格式如下:

file = open(file_name [, mode='r' [ , buffering=-1 [ , encoding = None ]]])

此格式中,用 [] 括起来的部分为可选参数,即可以使用也可以省略。其中,各个参数所代表的含义如下:

  • file:表示要创建的文件对象。

  • file_name:要创建或打开文件的文件名称,该名称要用引号(单引号或双引号都可以)括起来。需要注意的是,如果要打开的文件和当前执行的代码文件位于同一目录,则直接写文件名即可;否则,此参数需要指定打开文件所在的完整路径。

  • mode:可选参数,用于指定文件的打开模式。可选的打开模式如表 1 所示。如果不写,则默认以只读(r)模式打开文件。

  • buffering:可选参数,用于指定对文件做读写操作时,是否使用缓冲区(本节后续会详细介绍)。

  • encoding:手动设定打开文件时所使用的编码格式,不同平台的 ecoding 参数值也不同,以 Windows 为例,其默认为 cp936(实际上就是 GBK 编码)。

  • open() 函数支持的文件打开模式如表 1 所示

  •  

  • 模式意义注意事项
    r 只读模式打开文件,读文件内容的指针会放在文件的开头。 操作的文件必须存在。
    rb 以二进制格式、采用只读模式打开文件,读文件内容的指针位于文件的开头,一般用于非文本文件,如图片文件、音频文件等。  
    r+ 打开文件后,既可以从头读取文件内容,也可以从开头向文件中写入新的内容,写入的新内容会覆盖文件中等长度的原有内容。  
    rb+ 以二进制格式、采用读写模式打开文件,读写文件的指针会放在文件的开头,通常针对非文本文件(如音频文件)。  
    w 以只写模式打开文件,若该文件存在,打开时会清空文件中原有的内容。 若文件存在,会清空其原有内容(覆盖文件);反之,则创建新文件。
    wb 以二进制格式、只写模式打开文件,一般用于非文本文件(如音频文件)  
    w+ 打开文件后,会对原有内容进行清空,并对该文件有读写权限。  
    wb+ 以二进制格式、读写模式打开文件,一般用于非文本文件  
    a 以追加模式打开一个文件,对文件只有写入权限,如果文件已经存在,文件指针将放在文件的末尾(即新写入内容会位于已有内容之后);反之,则会创建新文件。  
    ab 以二进制格式打开文件,并采用追加模式,对文件只有写权限。如果该文件已存在,文件指针位于文件末尾(新写入文件会位于已有内容之后);反之,则创建新文件。  
    a+ 以读写模式打开文件;如果文件存在,文件指针放在文件的末尾(新写入文件会位于已有内容之后);反之,则创建新文件。  
    ab+ 以二进制模式打开文件,并采用追加模式,对文件具有读写权限,如果文件存在,则文件指针位于文件的末尾(新写入文件会位于已有内容之后);反之,则创建新文件。  

with上下文语法

文件操作时,一直强调打开的文件最后一定要关闭,否则会程序的运行造成意想不到的隐患。但是,即便使用 close() 做好了关闭文件的操作,如果在打开文件或文件操作过程中抛出了异常,还是无法及时关闭文件。在 Python 中,对应的解决方式是使用 with as 语句操作上下文管理器(context manager),它能够帮助我们自动分配并且释放资源。

with as 语句的基本语法格式为:

with 表达式 [as target]:
	代码块

此格式中,用 [] 括起来的部分可以使用,也可以省略。其中,target 参数用于指定一个变量,该语句会将 expression 指定的结果保存到该变量中。with as 语句中的代码块如果不想执行任何语句,可以直接使用 pass 语句代替。

举例:

假设有一个 a.txt 文件,其存储内容如下:

C语言中文网
http://c.biancheng.net

在和 a.txt 同级目录下,创建一个 .py 文件,并编写如下代码:

with open('a.txt', 'a') as f:
	f.write("\nPython教程")

运行结果为:

C语言中文网
http://c.biancheng.net
Python教程

数据存储

pickle模块

pickle 模块提供了以下 4 个函数供我们使用:

  1. dumps():将 Python 中的对象序列化成二进制对象,并返回;

  2. loads():读取给定的二进制对象数据,并将其转换为 Python 对象;

  3. dump():将 Python 中的对象序列化成二进制对象,并写入文件;

  4. load():读取指定的序列化数据文件,并返回对象。

以上这 4 个函数可以分成两类,其中 dumps 和 loads 实现基于内存的 Python 对象与二进制互转;dump 和 load 实现基于文件的 Python 对象与二进制互转。

json模块

json模块的主要功能是将序列化数据从文件里读取出来或者存入文件,该模块只有四个方法dump()、load()、dumps()、loads()。

json.dumps() 是把python对象转换成json对象的一个过程,生成的是字符串。 json.dump() 是把python对象转换成json对象生成一个fp的文件流,和文件相关。

json.loads()和json.load()的区别同上类似,加上s的方法是用来处理字符串类型的,而不加s是用来处理文件类型的。

常量、类或方法名注解
json.dump 方法,传入一个python对象,将其编码为json格式后存储到IO流中
json.dumps 方法,传入一个python对象,将其编码为json格式后存储到str中
json.load 方法,传入一个json格式的文件流,将其解码为python对象
json.loads 方法,传入一个json格式的str,将其解码为python对象
posted @ 2022-10-13 20:06  屋昂王  阅读(26)  评论(0)    收藏  举报