python第三课答案_Python 第三课笔记

本节内容

数据运算

集合操作

文件操作

字符编码与转码

函数介绍

局部变量

递归

数据运算

1.算数运算:

f855a55ec5501e2e1e3a597bb4667aa6.png

注:取模的用法主要判断奇偶数(看一个数是否能被2整除)

2.比较运算:

6ef404aaab1abf3e2e78ec1e37d5d94e.png

注:不等于一般用!=,一般都不用<>,<>也不方便阅读

3.赋值运算

a3e94ef1700999792e9014f6cf7b5cba.png

4、逻辑运算

a5c756277de7507e082b6d76b012d71e.png

5、成员运算

06127ac807127be41f941ec6e2b9422b.png

6、身份运算

8b8d03dd181614e072580820d3ee1d74.png

用法:

08821f39e77051f6ece770185e5b0483.png

7、位运算

4d3fba5ff62f192ffe134b4f7d1fc657.png

用法:

#!/usr/bin/python

a= 60 #60 = 0011 1100

b = 13 #13 = 0000 1101

c =0

c= a & b; #12 = 0000 1100

print "Line 1 - Value of c is", c

c= a | b; #61 = 0011 1101

print "Line 2 - Value of c is", c

c= a ^ b; #49 = 0011 0001

print "Line 3 - Value of c is", c

c= ~a; #-61 = 1100 0011

print "Line 4 - Value of c is", c

c= a << 2; #240 = 1111 0000

print "Line 5 - Value of c is", c

c= a >> 2; #15 = 0000 1111

print "Line 6 - Value of c is", c

注:

①异或 ^:相同取0,不同为1

9302b7f1628f9519de236523b576eee6.png

②与 &:有一个为0,取0;两个都为1,取1      (两个都为真才为真,否则为假)

775a5c43059830ae3935d77035969005.png

③或 |:有一个为1,取1  (任意为真就为真)

07ad35fb5c8e6dafb4ce2f6eb5c9cd0c.png

④取反(~a):单个数取反,获取的值= 取反的值-256*按位取反运算规则(按位取反再加1)   详解http://blog.csdn.net/wenxinwukui234/article/details/42119265

按位取反,只取一个值,a=60,按位取反就是1变0,0变1

1032f8beadfb141870689478b06c439d.png

⑤左移:向最左边移动n位,最右边补上n个0, 64>>1相当于除以2,64>>2相当于除以4

⑥右移:向最右边移动n位,最左边补上n个0,右移1位*2,右移2位*4

e44be03f0f10b09b4f4a1b8299d3d4bf.png

e56cdad3897d000d659c93ace2faba43.png

9f940b7e93e14842ffffd1ed7a4168ff.png

8、运算符优先级

368c3f39a6e790e4ae7b75755e9d1f53.png

总结:

①计算机中能表示的最小单位,是一个二进制位(bit)

②计算机中能存储的最小单位,是一个二进制位(bit)

③其实我们实际使用中,真正的存储是按照字节来存储的(8bit=1byte)

④任何一个英文字符至少需要一个字节表示

字节的单位换算:

1byte = 8bit

1kbyte = 1024byte

1Mbyte = 1024kbyte

1Gbyte = 1024Mbyte

1Tbyte = 1024Gbyte

集合操作

概念:集合是一个无序的,不重复的数据组合,它的主要作用如下:

去重,把一个列表变成集合,就自动去重了

关系测试,测试两组数据之前的交集、差集、并集等关系

定义:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

>>> name_1 = [1,2,3,4,7,8,7,10]#把列表转换为集合

>>> name_1 =set(name_1)#转换后,去重

>>> print(name_1,type(name_1))

{1, 2, 3, 4, 7, 8, 10}

View Code

关系测试

1、交集(intersection())

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

>>> name_1 = [1,2,3,4,7,8,7,10]>>> name_2 = [1,3,5,8,10]>>> name_1 =set(name_1)>>> name_2 =set(name_2)#输出结果

>>>name_1.intersection(name_2)

{8, 1, 10, 3}

View Code

2、并集(union())

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

>>> name_1 = [1,2,3,4,7,8,7,10]>>> name_2 = [1,3,5,8,10]>>> name_1 =set(name_1)>>> name_2 =set(name_2)#输出结果

>>>name_1.union(name_2)

{1, 2, 3, 4, 5, 7, 8, 10}

View Code

3、差集(difference())

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

>>> name_1 = [1,2,3,4,7,8,7,10]>>> name_2 = [1,3,5,8,10]>>> name_1 =set(name_1)>>> name_2 =set(name_2)#输出结果

>>>name_1.difference(name_2)

{2, 4, 7}

View Code

注:差集取的是数值在第一个集合中,但是不在第二个集合中(在我不在你)

4、子集issubset()

判断一个集合是否是另一个集合的子集

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

>>> name_1 = [1,2,3,4,7,8,7,10]>>> name_3 = [1,2,3,4]>>> name_1 =set(name_1)>>> name_3 =set(name_3)#输出结果

>>>name_3.issubset(name_1)

True

View Code

5、父集issuperset()

判断一个集合是否是另一个集合的父集

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

>>> name_1 = [1,2,3,4,7,8,7,10]>>> name_3 = [1,2,3,4]>>> name_1 =set(name_1)>>> name_3 =set(name_3)#输出结果

>>>name_1.issuperset(name_3)

True

View Code

6、对称差集(symmetric_difference())

把两个集合没有交集的数值取出来

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

>>> name_1 = [1,2,3,4,7,8,7,10]>>> name_2 = [1,3,5,8,10]>>> name_1 =set(name_1)>>> name_2 =set(name_2)#输出结果

>>>name_1.symmetric_difference(name_2)

{2, 4, 5, 7}

View Code

7、isdisjoint()

判断两个集合是否有交集,没有交集,则返回True

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

>>> name_1 = [1,2,3,4,7,8,7,10]>>> name_2 = [1,3,5,8,10]>>> name_3 = [11]>>> name_1 =set(name_1)>>> name_2 =set(name_2)>>> name_3 =set(name_3)#有交集

>>>name_1.isdisjoint(name_2)

False#无交集

>>>name_1.isdisjoint(name_3)

True

View Code

关系测试--符号

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

s = set([3, 5, 9, 10]) #创建一个数值集合

t= set("Hello") #创建一个唯一字符的集合

a= t | s #t 和 s的并集

b= t & s #t 和 s的交集

c= t – s #求差集(项在t中,但不在s中)

d= t ^ s #对称差集(项在t或s中,但不会同时出现在二者中)

基本操作:

t.add('x') #添加一项

s.update([10, 37, 42]) #在s中添加多项

使用remove()#可以删除一项:

t.remove('H')

len(s)#set的长度

xins#测试x是否是s的成员

xnot ins#测试x是否不是s的成员

s.issubset(t)

s<=t#测试是否s中的每一个元素都在t中

s.issuperset(t)

s>=t#测试是否t中的每一个元素都在s中

s.union(t)

s|t#返回一个新的set包含s和t中的每一个元素

s.intersection(t)

s&t#返回一个新的set包含s和t中的公共元素

s.difference(t)

s-t#返回一个新的set包含s中有但是t中没有的元素

s.symmetric_difference(t)

s^t#返回一个新的set包含s和t中不重复的元素

s.copy()#返回set “s”的一个浅复制

View Code

2. 文件操作

对文件操作流程

打开文件,得到文件句柄并赋值给一个变量

通过句柄对文件进行操作

关闭文件

现有一个文件

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

Somehow, it seems the love I knew was always the most destructive kind

不知为何,我经历的爱情总是最具毁灭性的的那种

Yesterday when I was young

昨日当我年少轻狂

The taste of life was sweet

生命的滋味是甜的

As rain upon my tongue

就如舌尖上的雨露

I teased at life asifit were a foolish game

我戏弄生命 视其为愚蠢的游戏

The way the evening breeze

就如夜晚的微风

May tease the candle flame

逗弄蜡烛的火苗

The thousand dreams I dreamed

我曾千万次梦见

The splendid things I planned

那些我计划的绚丽蓝图

I always built to last on weakandshifting sand

但我总是将之建筑在易逝的流沙上

I lived by nightandshunned the naked light of day

我夜夜笙歌 逃避白昼赤裸的阳光

And only now I see how the time ran away

事到如今我才看清岁月是如何匆匆流逝

Yesterday when I was young

昨日当我年少轻狂

So many lovely songs were waiting to be sung

有那么多甜美的曲儿等我歌唱

So many wild pleasures layin store forme

有那么多肆意的快乐等我享受

And so much pain my eyes refused to see

还有那么多痛苦 我的双眼却视而不见

I ran so fast that timeandyouth at last ran out

我飞快地奔走 最终时光与青春消逝殆尽

I never stopped to think what life was all about

我从未停下脚步去思考生命的意义

And every conversation that I can now recall

如今回想起的所有对话

Concerned itself with meand nothing elseat all

除了和我相关的 什么都记不得了

The game of love I played with arroganceandpride

我用自负和傲慢玩着爱情的游戏

And every flame I lit too quickly, quickly died

所有我点燃的火焰都熄灭得太快

The friends I made all somehow seemed to slip away

所有我交的朋友似乎都不知不觉地离开了

And only now I'm left alone to end the play, yeah

只剩我一个人在台上来结束这场闹剧

Oh, yesterday when I was young

噢 昨日当我年少轻狂

So many, many songs were waiting to be sung

有那么那么多甜美的曲儿等我歌唱

So many wild pleasures layin store forme

有那么多肆意的快乐等我享受

And so much pain my eyes refused to see

还有那么多痛苦 我的双眼却视而不见

There are so many songsin me that won't be sung

我有太多歌曲永远不会被唱起

I feel the bitter taste of tears upon my tongue

我尝到了舌尖泪水的苦涩滋味

The time has comefor me to pay foryesterday

终于到了付出代价的时间 为了昨日

When I was young

当我年少轻狂

View Code

基本操作

1.open()

open(文件路径,模式,字符编码)

1 open("song") #1、文件打开了

2 open("song").read() #2.读取内容

3 data=open("song").read() #3.给读取内容赋值

4

5 print(data)

【报错】

ps:运行文件时候没有指定字符编码,默认要设置一个字符编码集,windows默认的编码格式是gbk的

b88267a42596da115c1bd43ffd965714.png

增加字符编码部分内容,打印成功

data = open ("song", encoding="utf-8").read()print(data)

不符合编写规范,没有有关闭文件,所有都读出来,没有办法做文件操作

对文件进行操作,对文件打开在内存里,没有赋值给文件,不能找到,所以只能读,不能进行操作

赋一个变量,对变量操作

1 f = open ("song", encoding="utf-8") #f是一个文件句柄,文件的内存对象

2 data=f.read()3 print(data)

文件相当于指针

打开后,从第一行开始读,读到最后一行,

文件读完一遍就完了,从头读到尾之后,就没有东西,所以读取不到了,如果还想读取一遍,需要把光标移回去。

c61dbc824fc363e516b179b123b2c452.png

正确写法

#获取文件句柄

f = open("yesterday","r",encoding="utf-8")

#读取数据

data =f.read()

#打印读取的文件

print(data)

#关闭文件

f.close()

注:f 又叫文件句柄,它包含文件的文件名、文件的字符集、文件的大小、文件在硬盘上的起始位置

1 f = open ("song","w", encoding="utf-8") #f是一个文件句柄,文件的内存对象

2 data=f.read()3 print(data)4 f.write("快进快进看的即可")5

6 【运行结果】7 Traceback (most recent call last):8 File "D:/Python/s014/Day3/file_op.py", line 6, in

9 data=f.read()10 io.UnsupportedOperation: not readable

2、打开文件模式

r,英文:read,只读模式(默认)

w,英文:write,只写模式(不可读,不存在则创建新文件,存在则删除内容)

a,英文:append,追加模式(不可读,不存在则创建,存在则只追加内容)

"+"号表示同时读写某个文件

r+,可读写文件(可读;可写;可追加)

w+,可写读文件

a+,可追加和读文件

"U"表示在读取文件时,可以把\r\n自动转化为\n(与 r 或 r+ 模式同使用)

rU

r+U

"b"表示处理二进制文件

rb

wb

ab

1 f = open ("song","a", encoding="utf-8") #f是一个文件句柄,文件的内存对象

2

3 f.write("11111我爱北京天安门\n")4 f.write("22222天安门上太阳升\n")5f.close()

6 【运行结果打开文件】7 我爱北京天安门8 天安门上太阳升9 11111我爱北京天安门10 22222天安门上太阳升

1. readline()

如果一行一行读取文件

1 f = open ("song","r", encoding="utf-8") #f是一个文件句柄,文件的内存对象

2

3 #一行一行读

4 print(f.readline())5 print(f.readline())6 print(f.readline())7

8 【运行结果】9

10 Somehow, it seems the love I knew was always the most destructive kind11

12 不知为何,我经历的爱情总是最具毁灭性的的那种13

14 Yesterday when I was young

2.打印前五行

1 #打印前五行

2 for i in range(5):3 print(f.readline())

3.readlines()

循环读取文件中的内容,把文件中的每一行作为一个元素形成一个列表

1 #把文件循环一遍

2 print(f.readlines())3

4

5 【运行结果一坨坨不换行】6 ['Somehow, it seems the love I knew was always the most destructive kind\n', '不知为何,我经历的爱情总是最具毁灭性的的那种\n', 'Yesterday when I was young\n', '昨日当我年少轻狂\n', 'The taste of life was sweet\n', '生命的滋味是甜的\n', 'As rain upon my tongue\n', '就如舌尖上的雨露\n', 'I teased at life as if it were a foolish game\n', '我戏弄生命 视其为愚蠢的游戏\n', 'The way the evening breeze\n', '就如夜晚的微风\n', 'May tease the candle flame\n', '逗弄蜡烛的火苗\n', 'The thousand dreams I dreamed\n', '我曾千万次梦见\n', 'The splendid things I planned\n', '那些我计划的绚丽蓝图\n', 'I always built to last on weak and shifting sand\n', '但我总是将之建筑在易逝的流沙上\n', 'I lived by night and shunned the naked light of day\n', '我夜夜笙歌 逃避白昼赤裸的阳光\n', 'And only now I see how the time ran away\n', '事到如今我才看清岁月是如何匆匆流逝\n', 'Yesterday when I was young\n', '昨日当我年少轻狂\n', 'So many lovely songs were waiting to be sung\n', '有那么多甜美的曲儿等我歌唱\n', 'So many wild pleasures lay in store for me\n', '有那么多肆意的快乐等我享受\n', 'And so much pain my eyes refused to see\n', '还有那么多痛苦 我的双眼却视而不见\n', 'I ran so fast that time and youth at last ran out\n', '我飞快地奔走 最终时光与青春消逝殆尽\n', 'I never stopped to think what life was all about\n', '我从未停下脚步去思考生命的意义\n', 'And every conversation that I can now recall\n', '如今回想起的所有对话\n', 'Concerned itself with me and nothing else at all\n', '除了和我相关的 什么都记不得了\n', 'The game of love I played with arrogance and pride\n', '我用自负和傲慢玩着爱情的游戏\n', 'And every flame I lit too quickly, quickly died\n', '所有我点燃的火焰都熄灭得太快\n', 'The friends I made all somehow seemed to slip away\n', '所有我交的朋友似乎都不知不觉地离开了\n', "And only now I'm left alone to end the play, yeah\n", '只剩我一个人在台上来结束这场闹剧\n', 'Oh, yesterday when I was young\n', '噢 昨日当我年少轻狂\n', 'So many, many songs were waiting to be sung\n', '有那么那么多甜美的曲儿等我歌唱\n', 'So many wild pleasures lay in store for me\n', '有那么多肆意的快乐等我享受\n', 'And so much pain my eyes refused to see\n', '还有那么多痛苦 我的双眼却视而不见\n', "There are so many songs in me that won't be sung\n", '我有太多歌曲永远不会被唱起\n', 'I feel the bitter taste of tears upon my tongue\n', '我尝到了舌尖泪水的苦涩滋味\n', 'The time has come for me to pay for yesterday\n', '终于到了付出代价的时间 为了昨日\n', 'When I was young\n', '当我年少轻狂']

4.循环输出文件内容

1 #f.readlines() 相当于一个列表

2 #line作为一行,是其中的一个元素输出

3 for line inf.readlines():4 print(line)5

6 【运行结果】7 Somehow, it seems the love I knew was always the most destructive kind8

9 不知为何,我经历的爱情总是最具毁灭性的的那种10

11 Yesterday when I was young12 ……

5.去掉空行

1 for line inf.readlines():2 print(line.strip())

1 #f.readlines() 相当于一个列表

2 #line作为一行,是其中的一个元素输出

3 #第十行不输出,输出分割线,判断列表下标,取第几行元素

4 for index,line inenumerate(f.readlines()):5 if index==9:6 print("*************************************************")7 continue

8 print(line.strip())

几十个G的大文件不能使用以上方法实现

6.读取大文件

1 #不占用你内存,读一行覆盖一行

2 for line inf:3 print(line.strip())

运行结果一样,效率和资源不一样,f已经不是一个列表,是一个迭代器

我们正常循环读取文件中的每一行,如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

f = open("yesterday2","r",encoding="utf-8")for index,line inenumerate(f.readlines()):#当下标值为2时,不打印

if index == 2:print("--------data--------")continue

print(line.strip())

f.close()#输出

Somehow, it seems the love I knew was always the most destructive kind

不知为何,我经历的爱情总是最具毁灭性的的那种--------data--------昨日当我年少轻狂

View Code

这种方法已经达到我们的目的了,可以顺利的读取每一行,但是,当我们遇到2G,20G,甚至200G的文件时,你这样读取会导致内存不够用,会使程序变的很慢,因为你的内存只有几个G,你把几十个G的数据放到内存,内存肯定是受不了的,所以这种方法只适合小文件,不适合大文件。那怎么办呢?我们于是就有下面这种方法,如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

f = open("yesterday2",'r',encoding='utf-8')#计数器

count =0#f文件变成迭代器

for line inf:if count == 2:print("------data-----")

count+= 1

continue

print(line.strip())

count+= 1f.close()#输出结果

Somehow, it seems the love I knew was always the most destructive kind

不知为何,我经历的爱情总是最具毁灭性的的那种------data-----昨日当我年少轻狂

View Code

以上这种写法的好处在于,读取文件时,是一行一行的读取,而且,读取一行删除一行,内存中只保留一行。原因:f文件变成迭代器,它已经不再是一个列表的形式了,不能通过下标值来获取,需要一个计数器来计数。

7.循环判断第10行

1 count=02 for line inf:3 if count==9:4 print("************************************")5 count+=1

6 continue

7 print(line.strip())8 count+=1

8.读取文件的位置tell

1 f = open ("song","r", encoding="utf-8") #f是一个文件句柄,文件的内存对象

2 print(f.tell())#从文件开头3 print(f.readline())4 print(f.tell())5

6

7 【运行结果】8 09 Somehow, it seems the love I knew was always the most destructive kind10

11 72

tell计数是按照字符的个数,多少字符,记多少个数

1 f = open ("song","r", encoding="utf-8") #f是一个文件句柄,文件的内存对象

2 print(f.tell())3 print(f.read(5))#默认读所有,f.read(5)可以设置读五个

4 print(f.tell())5

6 【运行结果】7 08 Someh9 5

9.seek把光标移回去

f.seek(0)#把光标移回去

1 f = open ("song","r", encoding="utf-8") #f是一个文件句柄,文件的内存对象

2 print(f.tell())3 print(f.readline())4 print(f.readline())5 print(f.readline())6 print(f.tell())7 f.seek(0)#把光标移回去

8 print(f.readline())9

10 【运行结果】11 012 Somehow, it seems the love I knew was always the most destructive kind13

14 不知为何,我经历的爱情总是最具毁灭性的的那种15

16 Yesterday when I was young17

18 168

19 Somehow, it seems the love I knew was always the most destructive kind

修改文件的内容

将一个文件的内容,通过修改,写入到另外一个文件里

1、vim方式,将内容全部读到内存里修改

2、找到要修改的地方,写入新的文件里

(循环着一行一行读出来,每一行判断,找到替换修改的地方,放到新文件里,一行一行 的放入)

边读边写,不是要改的直接写入,是要改的地方 ,改完了再写入

需要同时打开两个文件

fb6fd4dd7df1bf2230a9685461226284.png

2ec760842ee418077366e0ff21f8defb.png

672184d92768077176d6916345bbbb77.png

with语句

为了避免打开文件后忘记关闭,可以通过管理上下文,即:

with open('log','r') as f:

....

如此方式,当with代码块执行完毕时,内部会自动关闭并释放文件资源。

在Python 2.7 后,with又支持同时对多个文件的上下文进行管理,即:

with open('log1') as obj1, open('log2') as obj2:pass

上面打开多个文件会导致一行代码过长,python官方建议,一行代码不超过80个字符,所以打开多个文件建议以下写法:

with open('log1') as obj1, \

open('log2') as obj2:pass

文件修改

1、在以后的工作中有时候会用到修改某个文件的内容,所以下面我们就讲讲,如何修改文件

修改文件,是先读文件,一边读和操作,再一边写(写需要命令一个新的文件,成功后,把老的文件删掉,把新文件重新命名成老文件)

#读老文件

f = open("yesterday","r",encoding="utf-8")

#写入新文件

f_new = open("yesterday_new",'w',encoding="utf-8")

for line in f:

#一边读新文件,修改内容

if "肆意的快乐等我享受" in line:

line = line.replace("肆意的快乐等我享受","肆意的快乐等kakak享受")

#一边写入新文件

f_new.write(line)

#关闭文件

f.close()

f_new.close()

yesterday文件:

So many lovely songs were waiting to be sung

有那么多甜美的曲儿等我歌唱

So many wild pleasures lay in store for me

有那么多肆意的快乐等我享受

And so much pain my eyes refused to see

还有那么多痛苦 我的双眼却视而不见

yesterday_new文件:

So many lovely songs were waiting to be sung

有那么多甜美的曲儿等我歌唱

So many wild pleasures lay in store for me

有那么多肆意的快乐等kaka享受

And so much pain my eyes refused to see

还有那么多痛苦 我的双眼却视而不见

字符转编码操作

编码介绍

1、须知:

在python 2中默认编码是 ASCII,而在python 3中默认编码是 unicode

unicode 分为utf-32 (占4个字节),utf-16(占两个字节),utf-8(占1-4个字节),所以utf-16 是最常用的unicode版本,但是在文件里存的还是utf-8,因为utf8省空间

在python 3,encode编码的同时会把stringl变成bytes类型,decode解码的同时会把bytes类型变成string类型

在unicode编码中 1个中文字符=2个字节,1个英文字符 = 1个字节,切记:ASCII是不能存中文字符的

utf-8是可变长字符编码,它是unicode的优化,所有的英文字符依然按ASCII形式存储,所有的中文字符统一是3个字节

unicode包含了所有国家的字符编码,不同字符编码之间的转换都需要经过unicode的过程

python本身的默认编码是utf-8

2.py2中的编码和转码的过程,如图:

65f8785d6d8ae4ee31671eff470b3c18.png

注:因为unicode是中间编码,任何字符编码之前的转换都必须解码成unicode,在编码成需要转的字符编码

3、py3的字符编码转换

在须知中已经说到python 3的编码,默认是unicode,所以字符编码之间的转换不需要decode过程,直接encode即可,代码如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

#-*-coding:gb2312 -*- #这个也可以去掉

importsysprint(sys.getdefaultencoding())

msg= "我爱北京天安门"

#msg_gb2312 = msg.decode("utf-8").encode("gb2312")

msg_gb2312 = msg.encode("gb2312") #默认就是unicode,不用再decode,喜大普奔

gb2312_to_unicode = msg_gb2312.decode("gb2312")

gb2312_to_utf8= msg_gb2312.decode("gb2312").encode("utf-8")print(msg)print(msg_gb2312)print(gb2312_to_unicode)print(gb2312_to_utf8)in python3

View Code

注:在python 3,encode编码的同时会把stringl变成bytes类型,decode解码的同时会把bytes类型变成string类型,所以你就不难看出encode后的把它变成了一个bytes类型的数据。还有需要特别注意的是:不管是否在python 3的文件开头申明字符编码,只能表示,这个python文件是这个字符编码,文件中的字符串还是unicode

总结:

uniocode能识别所有字符编码的字符串

在python 2中,字符编码之间的转化需要通过unicode才能转换,所以打印时,可以是使用unicode,也可以使用对应的字符编码(文件开头指定编码),打印字符或者字符串,因为py2中没有对字符和字节做明显区分,所以才混导致这样的结果。

在python 3中,只有通过Unicode去识别字符的,如果转成编码成对应编码格式了,就直接变成对应编码的bytes类型的字节码,也就是二进制,需要识别,必须解码成Unicode才能识别

py3中如果说在文件开头已经指定了文件编码,为啥文件中用到的还是uniocde呐?因为py3中的对应编码是二进制,是bytes类型,是不能识别的,能识别的只有Unicode。因为py3中对字符和字节做了明显的区分,所以出现3和4阐述的情况。

函数和过程

在我们以往的学习编程的过程当中,碰到的最多的两张编程方式或者说编程方法:面向过程和面向对象。其实不管是哪一种,其实都是编程的方法论而已。但是现在有一种更古老的编程方式:函数式编程,以它的不保存的状态,不修改变量等特性,重新进入我们的视野。

面向对象 --->类 ---->class

面向过程 --->过程--->def

函数式编程-->函数--->def

函数是什么?

函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,具体区别,我们后面会讲,编程中的函数在英文中也有很多不同的叫法。在BASIC中叫做subroutine(子过程或子程序),在Pascal中叫做procedure(过程)和function,在C中只有function,在Java里面叫做method。

定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可

1.定义函数

def test():

"the funcation details"

print("in the test funcation")

return 0

def #定义函数的关键字

test #函数名

() #定义形参,我这边没有定义。如果定义的话,可以写成:def test(x): 其中x就是形式参数

"the funcation details" # 文档描述(非必要,但是强烈建议你为你的函数添加详细信息,方便别人阅读)

print #泛指代码块或者程序逻辑处理

return #定义返回值

2.定义过程

#定义过程

def test_2():

"the funcation details"

print("in the test funcation")

注:从上面两个例子看出来,函数和过程,无非就是函数比过程多了一个return的返回值,其他的也没什么不一样。

3、两者比较:

#定义函数

def test_1():

"the funcation details"

print("in the test funcation")

return 0

#定义过程

def test_2():

"the funcation details"

print("in the test funcation")

a = test_1()

b = test_2()

print(a)

print(b)

#输出

in the test funcation

in the test funcation

#输出返回值

0

#没有return ,返回为空

None

小结:不难看出,函数和过程其实在python中没有过多的界限,当有return时,则输出返回值,当没有return,则返回None

过程是没有返回值的函数

为什么使用函数

特性:

减少重复代码

使程序变的可扩展

使程序变得易维护

没有函数的编程只是在写逻辑(功能),想脱离函数,重用你的逻辑,唯一的方法就是拷贝

假设我们编写好了一个逻辑(功能),用来以追加的方式写日志:

with open('a.txt','ab') as f:

f.write('end action')

#现在有三个函数,每个函数在处理完自己的逻辑后,都需要使用上面这个逻辑,那么唯一的方法 就是,拷贝三次这段逻辑

def test1():

print 'test1 starting action...'

with open('a.txt','ab') as f:

f.write('end action')

def test2():

print 'test2 starting action...'

with open('a.txt','ab') as f:

f.write('end action')

def test3():

print 'test3 starting action...'

with open('a.txt','ab') as f:

f.write('end action')

那么假设有>N个函数都需要使用这段逻辑,你可以拷贝N次吗?

def logger_test():

with open('a.txt','ab') as f:

f.write('end action')

def test1():

print('test1 starting action...' )

logger_test()

def test2():

print ('test2 starting action...' )

logger_test()

def test3():

print ('test3 starting action...' )

logger_test()

注:如果遇到代码逻辑变了,用以前拷贝n次的方法,那什么时候拷贝完啊,而且中间有遗漏怎么办,如果用了函数,我们只需要改这个函数的逻辑即可,不用改其他任何地方。

import time

def logger_test():

time_format='%Y-%m-%d %X'

time_current=time.strftime(time_format)

with open('a.txt','ab') as f:

f.write('time %s end action' %time_current)

def test1():

print ('test1 starting action...' )

logger_test()

def test2():

print ('test2 starting action...' )

logger_test()

def test3():

print ('test3 starting action...' )

logger_test()

返回值

1.return作用

return其实有两个作用:

需要用一个变量来接受程序结束后返回的结果

它是作为一个结束符,终止程序运行

def test():

print("in the test_1")

return 0

print("the end") #结果中没有打印

x = test()

print(x)

#输出

in the test_1 #第一次打印

0 #结果返回值

注:从上面的代码可以看出,return 0后面的代码就不执行了,只执行return前面的代码;变量x接受了test()函数结束后的返回结果

2.返回多个值

上面我们试了返回一个常量值,或者说一个对象值,下面我们来试试,不返回值,或者说返回多个值得情况

def test_1():

print("in the test_1")

def test_2():

print("in the test_2")

return 0

def test_3():

print("in the test_3")

return 1,"hello",["qigao","shuaigao"],{"name":"qigao"}

x = test_1()

y = test_2()

z =test_3()

print(x)

print(y)

print(z)

#输出

in the test_1

in the test_2

in the test_3

None #x的值

0 #y的值

(1, 'hello', ['qigao', 'shuaigao'], {'name': 'qigao'}) #z的值

从上面的例子可以看出:

没有定义,返回值数=0,返回:None

只定义了1个返回值,返回值=1 ,返回:定义的那个值,或者说定义的那个object

定义了2个以上,返回值 > 1,返回:1个元组(tuple)

提问:这边我们不经意的要问,为什么要有返回值?

因为我们想要想要这个函数的执行结果,这个执行结果会在后面的程序运行过程中需要用到。

有参数的函数

def test(x,y): #x,y是形参

print(x)

print(y)

test(1,2) #1和2是实参

#输出

1

2

1.位置参数

位置参数需要一一对应,多了少了都不行

从上面的例子可以看出,实际参数和形式参数是一一对应的,如果调换位置,x和y被调用的时,位置也会互换,代码如下:

def test(x,y):

print(x)

print(y)

print("--------互换前-----")

test(1,2)

print("--------互换后-----")

test(2,1)

#输出

--------互换前-----

1

2

--------互换后-----

2

1

①多一个参数

def test(x,y):

print(x)

print(y)

print("--------多一个参数----")

test(1,2,3)

#输出

--------多一个参数----

Traceback (most recent call last):

File "D:/PycharmProjects/pyhomework/day3/函数_带参数.py", line 8, in

test(1,2,3)

TypeError: test() takes 2 positional arguments but 3 were given #test()函数需要传两个实参,你传了三个实参

②少一个参数

ef test(x,y):

print(x)

print(y)

print("--------少一个参数----")

test(1)

#输出

--------少一个参数----

Traceback (most recent call last):

File "D:/PycharmProjects/pyhomework/day3/函数_带参数.py", line 8, in

test(1)

TypeError: test() missing 1 required positional argument: 'y' #没有给y参数传实参

2.关键字参数

参数顺序可以换吗?形参叫什么名就给赋什么值

def test(x,y):

print(x)

print(y)

print("--------互换前------")

test(x=1,y=2)

print("--------互换后------")

test(y=2,x=1)

#输出

--------互换前------

1

2

--------互换后------

1

2

981c6ad44b4ae679dddabc77dd641a4b.png

可不可以位置参数和关键字参数结合起来用?

①位置参数在前,关键字参数在后

def test(x,y):

print(x)

print(y)

test(1,y=2)

#输出

1

2

把后面关键字不传给y,我传给x,代码如下:

def test(x,y):

print(x)

print(y)

test(1,x=2)

#输出

Traceback (most recent call last):

File "D:/PycharmProjects/pyhomework/day3/函数_带参数.py", line 8, in

test(1,x=2)

TypeError: test() got multiple values for argument 'x' #给x形参传的值过多

报错的意思是:给形参x传的值过多。这种报错的原因是:实参1已经传给了形参x,后面的x=2又传了一次,所以报错。

②关键字在前,位置参数在后

def test(x,y):

print(x)

print(y)

test(y=2,1)

#输出

File "D:/PycharmProjects/pyhomework/day3/函数_带参数.py", line 8

test(y=2,1)

^

SyntaxError: positional argument follows keyword argument # 关键字参数在位置参数的前面

我去,看来这样不行。那我位置参数放前面,中间放关键字参数总行了吧!代码如下:

def test(x,y,z):

print(x)

print(y)

test(1,y=2,3)

#输出

File "D:/PycharmProjects/pyhomework/day3/函数_带参数.py", line 8

test(1,y=2,3)

^

SyntaxError: positional argument follows keyword argument

还是一样的错误,只能把关键字参数放最后试试!

def test(x,y,z):

print(x)

print(y)

print(z)

test(1,2,z=3)

#输出

1

2

3

那我最后两个用关键字参数

def test(x,y,z):

print(x)

print(y)

print(z)

test(1,z=2,y=3)

#输出

1

3

2

这样也是可以的,所以,得出一个结论:关键字参数是不能写在位置参数前面的。

总结

既有关键字,又有位置参数时,是按位置参数的顺序来

关键字参数是不能写在位置参数的前面的

3.默认参数

默认参数指的是,我们在传参之前,先给参数制定一个默认的值。当我们调用函数时,默认参数是非必须传递的。

def test(x,y=2):

print(x)

print(y)

print("-----data1----")

test(1) #没有给默认参数传值

print("-----data2----")

test(1,3) #给默认参数传位置参数

print("-----data3----")

test(1,y=3) #给默认参数传关键字参数

#输出

-----data1----

1

2

-----data2----

1

3

-----data3----

1

3

默认参数用途:

安装默认软件(def test(x,soft=True))

传递一下默认的值(定义mysql的默认端口号:def count(host,port=3306))

默认参数,调用函数时,可有可无

用途是,把一些值,固定住。

参数组

不固定个数的形参,如何定义

参数组的定义

定义多个实参,把实参放到元组里

非固定位置参数传参(*args)

非固定关键字传参(**kwargs)

下面我们就来说说这两种方式传参:

1、非固定位置参数传参

①功能:接收N个位置参数,转换成元组的形式。

②定义,代码如下:

def test(*args): #形参必须以*开头,args参数名随便定义,但是最好按规范来,定义成args

print(args)

test(1,2,3,4,5) #输入多个位置参数

#输出

(1, 2, 3, 4, 5) #多个参数转换成元组

③传入列表

def test(*args):

print(args)

print("-------data1-----")

test() #如果什么都不传入的话,则输出空元组

print("-------data2-----")

test(*[1,2,3,4,5]) #如果在传入的列表的前面加*,输出的args = tuple([1,2,3,4,5])

print("-------data3-----")

test([1,2,3,4,5]) #如果再传入的列表前不加*,则列表被当做单个位置参数,所以输出的结果是元组中的一个元素

#输出

-------data1-----

()

-------data2-----

(1, 2, 3, 4, 5)

-------data3-----

([1, 2, 3, 4, 5],)

④位置参数和非固定位置参数

def test(x,*args):

print(x) #位置参数

print(args) #非固定参数

test(1,2,3,4,5,6)

#输出

1

(2, 3, 4, 5, 6)

从上面看出,第1个参数,被当做位置参数,剩下的被当做非固定位置参数。

第一个值,给x,其他值传ages一个元组

2、非固定关键字传参

①功能:把N个关键字参数(个数不固定),转换成字典形式

②定义,代码如下:

ef test(**kargs):

print(kargs)

print(kargs["name"])

print(kargs["age"])

test(name="cola",age=3,sex="boy")

运行结果

{'name': 'cola', 'age': 3, 'sex': 'boy'}

③传入字典

def test(**kargs):

print(kargs)

print(kargs["name"])

print(kargs["age"])

test(name="cola",age=3,sex="boy")

#位置参数可用否

test(**{"name":"cola","age":3})

#运行结果

{'name': 'cola', 'age': 3}

④配合位置参数使用

和其他参数一起使用

只输入一个参数值,是否可以只指定一个值

def test(name,**kargs):

print(name)

print(kargs)

test("baby")#只输入一个参数值

运行结果:

baby

{}

调用语句

test("baby",age=3,sex="boy")

运行结果:

baby

{'age': 3, 'sex': 'boy'}

总结,集合内容必须以关键字参数的形式赋值

⑤位置参数、关键字和非固定关键字参数

提示:参数组一定要往最后放

def test(name, age=4, **kwargs):

print(name)

print(age)

print(kwargs)

print("----------data1--------")

test("Cola", sex='M', hobby='tesla')

print("----------data2--------")

test("Cola", 5, sex='M', hobby='tesla')

print("----------data3--------")

test("Cola", sex='M', hobby='tesla', age=18) # age关键字参数放到最后,也可以的

----------data1--------

Cola

4

{'sex': 'M', 'hobby': 'tesla'}

----------data2--------

Cola

5

{'sex': 'M', 'hobby': 'tesla'}

----------data3--------

Cola

18

{'sex': 'M', 'hobby': 'tesla'}

注:就是说,如果遇到一个关键字传参和非固定关键字传参,前后放的位置是不影响传参的,但是我们一般还是按顺序来。

def test(name, age=4, **kwargs):

print(name)

print(age)

print(kwargs)

print("----------data--------")

test("Cola",8, sex='M', hobby='tesla', age=18)

输出

----------data3--------

Traceback (most recent call last):

File "C:/Users/huojia/PycharmProjects/Day1/file/tmp.py", line 15, in

test("Cola",8, sex='M', hobby='tesla', age=18)

TypeError: test() got multiple values for argument 'age'

看来是不可以的,为什么?因为age=19是关键字参数,而后面的*args是非固定位置参数,说白了不管*args传入几个字,它的本质都是位置参数,上面我们提到关键字参数是不能再位置参数的前面,所以报错了。

def test(name,age=18,*args,**kargs):

print(name)

print(age)

print(args)

print(kargs)

test("baby",33,hobby="tesla",sex="boy")

--------运行结果---------

baby

33

()

{'hobby': 'tesla', 'sex': 'boy'}

关键字参数前输入的参数将被存储到元组里

test("baby",33,"haha","hoho","hehe","huhuih","hkjhkjhk",hobby="tesla",sex="boy")

运行结果

baby

33

('haha', 'hoho', 'hehe', 'huhuih', 'hkjhkjhk')

{'sex': 'boy', 'hobby': 'tesla'}

总结

参数分为位置参数、关键字参数、默认参数、非固定位置参数和非固定关键字参数

位置参数之前传参,位置是不能调换的,多一个或者少一个参数都是不可以的。

关键字参数是不能放在位置参数前面的。

函数传参的位置一次是,位置参数,默认参数、非固定位置参数、非固定关键字参数(def test(name,age=18,*args,**kwargs))

关键字传参,可以不用考虑位置的前后问题

一个函数体内部调用另外一个函数

调用在定义之前,找不到Logger

def test(name,age=18,*args,**kargs):

print(name)

print(age)

print(args)

print(kargs)

logger("test4")

test("baby",33,"haha","hoho","hehe","huhuih","hkjhkjhk",hobby="tesla",sex="boy")

def logger(source):

print("from %s "%source)

运行结果

baby

33

('haha', 'hoho', 'hehe', 'huhuih', 'hkjhkjhk')

{'hobby': 'tesla', 'sex': 'boy'}

Traceback (most recent call last):

File "D:/Python/s014/Day3/def.py", line 10, in

test("baby",33,"haha","hoho","hehe","huhuih","hkjhkjhk",hobby="tesla",sex="boy")

File "D:/Python/s014/Day3/def.py", line 7, in test

logger("test4")

NameError: name 'logger' is not defined

程序从上到下执行

若果将调用语句放在最后就不会报错

def test(name,age=18,*args,**kargs):

print(name)

print(age)

print(args)

print(kargs)

logger("test4")

def logger(source):

print("from %s "%source)

test("baby",33,"haha","hoho","hehe","huhuih","hkjhkjhk",hobby="tesla",sex="boy")

运行结果:

baby

33

('haha', 'hoho', 'hehe', 'huhuih', 'hkjhkjhk')

{'sex': 'boy', 'hobby': 'tesla'}

from test4

局部变量

局部变量:顾名思义,指在局部生效,定义在函数体内的变量只能在函数里面生效,出个这个函数体,就不能找到它,这个函数就是这个变量的作用域。

下面我们就用事实说话吧,请看如下代码:

def test(name):

print("before change:", name)

name = "Alex LLLL" # 局部变量name,只能在这个函数内生效,这个函数就是这个变量的作用域

print("after change:", name)

name = "alex"

print("-----函数内部调用test-----")

test(name)

print("------函数外打印name----")

print(name)

全局变量

全局变量:指的是在整个程序中都生效的变量,在整个代码的顶层声明。

代码如下:

school = "O edu" # 定义全局变量

def test_1():

print("school:", school)

def test_2():

school = "ab linux "

print("school:", school)

print("------test_1----")

test_1()

print("------test_2----")

test_2()

print("----打印school--")

print("school:", school)

------test_1----

school: O edu

------test_2----

school: ab linux

----打印school--

school: O edu

局部变量对全局不能产生任何影响,小范围内有效

全局变量的优先级是低于局部变量的,当函数体内没有局部变量,才会去找全局变量。

①函数里面修改全局变量

改前用global先声明一下全局变量

将全局变量重新赋值

school = "O edu" # 定义全局变量

def test_1():

print("school:", school)

def test_2():

global school # 用global关键字声明全局变量

school = "ab linux " #将全局变量重新赋值

print("school:", school)

print("------test_1----")

test_1()

print("------test_2----")

test_2()

print("----打印school--")

print("school:", school)

运行结果

------test_1----

school: O edu

------test_2----

school: ab linux

----打印school--

school: ab linux

③修改列表

names = ['alex', "BB"] # 定义一个列表

def test():

names[0] = "金角大王"

print(names)

print("--------test-----")

test()

print("------打印names--")

print(names)

# 输出

--------test-----

['金角大王', 'BB']

------打印names--

['金角大王', 'BB']

从上面的例子可以看出,列表names被当做在函数中全局变量,重新赋值了,是可以被修改的。

小结:1、只有字符串和整数是不可以被修改的,如果修改,需要在函数里面声明global。

2、但是复杂的数据类型,像列表(list)、字典(dict)、集合(set),包括我们后面即将要学的类(class)都是可以修改的。

总结

在子程序(函数)中定义的变量称为局部变量,在程序一开始定义的变量称为全局变量。

全局变量的作用域是整个程序,局部变量的作用域是定义该变量的子程序(函数)。

当全局变量和局部变量同名时:在定义局部变量的子程序内,局部变量起作用;在其他地方,全局变量起作用。

递归

在函数内部,可以调用其他函数。但是一个函数在内部调用自身,这个函数被称为递归函数。

无限循环,最多只能调999层

afee2687e43da42389c43be412a413e0.png

def calc(n):

print(n)

if int(n/2) == 0: #结束符

return n

return calc(int(n/2)) #调用函数自身

m = calc(10)

print('----->',m)

#输出结果

10

5

2

1

-----> 1 #最后返回的值

总结

必须要有一个明确的结束条件。

每次进入更深一层的递归时,问题规模相比上次递归都应该少(问题规模:比如你第1次传进的是10,第2次递归应该是9...依次越来越少,不能越来越多)。

递归的效率不高,递归层次过多会导致内存溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈贞,每当函数返回,栈就会减一层栈贞。由于栈的大小不是无限的,所以递归的次数过多,会导致栈溢出)。

函数式编程介绍

函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。

函数式编程中的函数这个术语不是指计算机中的函数(实际上是Subroutine),而是指数学中的函数,即自变量的映射。也就是说一个函数的值仅决定于函数参数的值,不依赖其他状态。比如sqrt(x)函数计算x的平方根,只要x不变,不论什么时候调用,调用几次,值都是不变的。

Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

一、定义

简单说,"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。

主要思想是把运算过程尽量写成一系列嵌套的函数调用。举例来说,现在有这样一个数学表达式:

(1 + 2) * 3 - 4

传统的过程式编程,可能这样写:

var a = 1 + 2;

var b = a * 3;

var c = b - 4;

函数式编程要求使用函数,我们可以把运算过程定义为不同的函数,然后写成下面这样:

var result = subtract(multiply(add(1,2), 3), 4);

这段代码再演进以下,可以变成这样

add(1,2).multiply(3).subtract(4)

这基本就是自然语言的表达了。再看下面的代码,大家应该一眼就能明白它的意思吧:

merge([1,2],[3,4]).sort().search("2")

因此,函数式编程的代码更容易理解。要想学好函数式编程,不要玩python,学lisp,Erlang,Hashshell

高阶函数

高阶函数:变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数。

其实说白了,高阶函数功能就是:把函数本身当做一个参数,传到另一个函数中,然后在这个函数中做处理。代码如下:

#普通函数

def test_1(a,b):

return a+b

#高阶函数

def test_2(a,b,f):

return f(a)+f(b)

print("------test_1-----")

res = test_1(1,-3)

print(res)

print("------test_2-----")

res = test_2(1,-3,abs) #把abs这个内置函数当做参数传进去

print(res)

#输出

------test_1-----

-2

------test_2-----

4

eval函数

在我们使用一些类似于字典的字符串时,虽然它看起来很像字典,但是在它的最外层多了引号,说明它是字符串,但是我们如何把它转换成字典呐,这就用到了eval()函数,看看eval()函数是如何把字符串转换成字典的,下面就来看看见证奇迹的时刻:

#定义一个类似于字典的字符串,把值赋给arg

>>> arg = '''{

'backend': 'www.oldboy.org',

'record':{

'server': '100.1.7.9',

'weight': 20,

'maxconn': 30

}

}'''

#这边根据键取值报错,说明它是一个字符串,不是字典

>>> arg["backend"]

Traceback (most recent call last):

File "", line 1, in

TypeError: string indices must be integers

#通过eval()函数把字符串转成字典

>>> arg = eval(arg)

#显示的类型是字典

>>> type(arg)

>>> arg

{'record': {'server': '100.1.7.9', 'weight': 20, 'maxconn': 30}, 'backend': 'www.oldboy.org'}

#通过键能获取对应的值,说明字符串成功转成字典

>>> arg["backend"]

'www.oldboy.org'

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值