Python之路-Day3

Python之路-Day3
本次课程路径:https://www.cnblogs.com/alex3714/articles/5740985.html

Alex推荐书籍:
追风筝的人
白鹿原
林达看美国:华人在美国定居后写信的方式讲述美国发展史,中国人眼中的美国。培养客观的世界观

列表和字符串的区别:
列表可以增删改查,字符串不支持改,所谓的改其实就是把整个字符串用一个新的字符串覆盖掉

集合:
集合是一个无序的,不重复的数据组合,它的主要作用如下:
列表重要作用:
去重:把一个列表变成集合,就自动去重了
关系测试:测试两组数据之前的交集、差集、并集等关系

常用操作:
设置集合使用set,集合形成后自动去重
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray

list_1 = [1,4,5,7,3,6,7,9]
list_1 = set(list_1)

print(list_1,type(list_1))
输出结果:
{1, 3, 4, 5, 6, 7, 9} <class 'set'>

取交集:
list_1 = [1,4,5,7,3,6,7,9]
list_1 = set(list_1)
list_2 = set([2,6,0,66,22,8,4])
print(list_1,list_2)
#交集:取出重复的
#list_1.intersection(list_2)
print( list_1.intersection(list_2))
print(list_1 & list_2)
结果:
{4, 6}

#并集:取出不重复的
print( list_1.union(list_2))
print( list_1 | list_2)
结果:
{0, 1, 2, 3, 4, 5, 6, 7, 66, 9, 8, 22}

#差集:list_1有list_2没有的
print( list_1.difference(list_2))
print(list_1 - list_2)
结果:
{1, 3, 5, 7, 9}

#子集:父集包含子集内容
list_3 = set([1,3,7])
print( list_3.issubset(list_1))

#父集:
print( list_1.issuperset(list_3))
结果:
True
True

#对称差集:list_1、list_2合并后彼此都没有的取出
print(list_1.symmetric_difference(list_2))
print(list_1 ^ list_2)

集合的增删改查:

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

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

t.remove('H') # 使用remove()可以删除一项:

t.pop('x') # 删除并返回删除值

t.discard('x') # 删除x的值不存在返回None,并不会报错,remove会报错

len(s) #set 的长度

x in s
测试 x 是否是 s 的成员

x not in s
测试 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”的一个浅复制

运算符:

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中,但不会同时出现在二者中)

文件操作:

对文件操作流程
打开文件,得到文件句柄并赋值给一个变量
通过句柄对文件进行操作
关闭文件

现有文件如下:
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 as if it 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 weak and shifting sand
但我总是将之建筑在易逝的流沙上
I lived by night and shunned 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 lay in store for me
有那么多肆意的快乐等我享受
And so much pain my eyes refused to see
还有那么多痛苦 我的双眼却视而不见
I ran so fast that time and youth 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 me and nothing else at all
除了和我相关的 什么都记不得了
The game of love I played with arrogance and pride
我用自负和傲慢玩着爱情的游戏
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 lay in store for me
有那么多肆意的快乐等我享受
And so much pain my eyes refused to see
还有那么多痛苦 我的双眼却视而不见
There are so many songs in me that won't be sung
我有太多歌曲永远不会被唱起
I feel the bitter taste of tears upon my tongue
我尝到了舌尖泪水的苦涩滋味
The time has come for me to pay for yesterday
终于到了付出代价的时间 为了昨日
When I was young
当我年少轻狂

练习脚本:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray
f = open("yesterday",'r',encoding="utf-8") #文件句柄,就是文件的内存对象,包含文件名,字符集,硬盘起始位置等.中间的rw代表读写模式,不写默认为只读模式
#data = f.read()
#data2 = f.read()
#print(data)
#print('------------data2-----------',data2) #第二次读时会从文件末尾读起,因此data2的调用读取是没有任何返回值的
'''
f.write("\nwhen i was young i listen to the redio\n") #写入是在读取文件的末尾进行写入
data = f.read()
print('----read',data)

f.close() #文件关闭
'''
#for i in range(5): #读5行
# print(f.readline()) #读取一行
'''
#低效率,把文件读到内存进行处理
for index,line in enumerate(f.readlines()):
if index == 9
print("------分割线---------")
continue
print(line.strip()) # strip把空格和换行去掉
'''
#高效,一行行处理,处理完释放,在第10行用分割线隔开
count = 0
for line in f:
if count == 9:
print("------分割线---------")
count += 1
continue
print(line)
count += 1

#光标位置移动,tell和seek
print(f.tell()) #指针所在位置
print(f.readline()) #打印指针所在位置的一行
#print(f.read()) #只打印所在行的前5个字符
print(f.tell()) #打印光标当前所在位置
f.seek(10) #光标移回原始位置,括号所填写的数字代表字符,要回到哪个字符位置,从当前位置到第一个换行符
print(f.readline()) #又回到了Somehow的一行,并且打印从第10个字符开始往后的

print(f.encoding) #打印出此文件的编码类型,utf-8#print(f.fileno()) #返回内存中的编号
print(f.name()) #打印文件名
print(f.isatty()) #打开一个终端设备,与打印机交互等
print(f.seekable()) #终端设备等无法移动光标,seekable判断是否是光标可移动的文件,如果是则返回true
print(f.readable()) #判断文件是否可以读,返回true或false
print(f.flush()) #默认内存缓存写满再同步磁盘,此命令可强制同步至磁盘

权限:
f = open("yesterday",'r+',encoding="utf-8") #文件读写权,以追加方式写,常用
f = open("yesterday",'w+',encoding="utf-8") #文件写读权,创建文件再写
f = open("yesterday",'a+',encoding="utf-8") #文件追加读,打开文件追加读写
f = open("yesterday",'rb') #以二进制格式读文件,二进制无需指定编码类型,网络传输
f = open("yesterday",'wb') #以二进制格式写文件
f.write("hello binary\n".encode()) #使用默认utf-8方式写入到二进制文件

f.seek(10) #先光标移动到第10个字符
f.truncate(10) #截断,不写默认清空文件,无论光标在哪都从头10个字符后全部截断

文件的修改:
1、生成新文件yesterday2.bak
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray

f = open("yesterday2",'r',encoding="utf-8")
f_new = open("yesterday2.bak","w",encoding="utf-8")

for line in f:
if "肆意的快乐等我享受" in line:
line = line.replace("肆意的快乐等我享受","肆意的快乐等Donray去享受")
f_new.write(line)
f.close()
f_new.close()


进度条显示脚本:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray
import sys,time

for i in range(20): #循环20次
sys.stdout.write("#") #打印出变量#,20次
sys.stdout.flush() #固定刷入硬盘
time.sleep(0.1) #间隔0.1秒

文件截取:
f = open("yesterday",'a',encoding="utf-8") #模式改为a追加
f.seek(10) #先光标移动到第10个字符
f.truncate(10) #截断,不写默认清空文件,无论光标在哪都从头10个字符后全部截断

文件读写并修改文件:


data = open("yesterday",'r',encoding="utf-8").read() #打开yesterday文件,把内容read出来存为变量data。本地windows默认编码为gbk,python编码却是utf-8如果不指定编码格式默认用系统的gbk来打开,因此python无法读取,因此输入encoding="utf-8"让程序使用指定的utf-8格式打开此文件即可。中间r表示只读模式,默认不写也是只读,也可以改为w写模式,但是如果以w写模式打开文件,默认就会清空文件内容,慎用。
print(data)


基本操作:
f = open('lyrics') #打开文件
first_line = f.readline()
print('first line:',first_line) #读一行
print('我是分隔线'.center(50,'-'))
data = f.read()# 读取剩下的所有内容,文件大时不要用
print(data) #打印文件

f.close() #关闭文件

 

打开文件的模式有:
r,只读模式(默认)。
w,只写模式。【不可读;不存在则创建;存在则删除内容;】
a,追加模式。【可读; 不存在则创建;存在则只追加内容;】
"+" 表示可以同时读写某个文件

r+,可读写文件。【可读;可写;可追加】
w+,写读
a+,同a
"U"表示在读取时,可以将 \r \n \r\n自动转换成 \n (与 r 或 r+ 模式同使用)

rU
r+U
"b"表示处理二进制文件(如:FTP发送上传ISO镜像文件,linux可忽略,windows处理二进制文件时需标注)

rb
wb
ab

def close(self): # real signature unknown; restored from __doc__
"""
Close the file.

A closed file cannot be used for further I/O operations. close() may be
called more than once without error.
"""
pass

def fileno(self, *args, **kwargs): # real signature unknown
""" Return the underlying file descriptor (an integer). """
pass

def isatty(self, *args, **kwargs): # real signature unknown
""" True if the file is connected to a TTY device. """
pass

def read(self, size=-1): # known case of _io.FileIO.read
"""
注意,不一定能全读回来
Read at most size bytes, returned as bytes.

Only makes one system call, so less data may be returned than requested.
In non-blocking mode, returns None if no data is available.
Return an empty bytes object at EOF.
"""
return ""

def readable(self, *args, **kwargs): # real signature unknown
""" True if file was opened in a read mode. """
pass

def readall(self, *args, **kwargs): # real signature unknown
"""
Read all data from the file, returned as bytes.

In non-blocking mode, returns as much as is immediately available,
or None if no data is available. Return an empty bytes object at EOF.
"""
pass

def readinto(self): # real signature unknown; restored from __doc__
""" Same as RawIOBase.readinto(). """
pass #不要用,没人知道它是干嘛用的

def seek(self, *args, **kwargs): # real signature unknown
"""
Move to new file position and return the file position.

Argument offset is a byte count. Optional argument whence defaults to
SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values
are SEEK_CUR or 1 (move relative to current position, positive or negative),
and SEEK_END or 2 (move relative to end of file, usually negative, although
many platforms allow seeking beyond the end of a file).

Note that not all file objects are seekable.
"""
pass

def seekable(self, *args, **kwargs): # real signature unknown
""" True if file supports random-access. """
pass

def tell(self, *args, **kwargs): # real signature unknown
"""
Current file position.

Can raise OSError for non seekable files.
"""
pass

def truncate(self, *args, **kwargs): # real signature unknown
"""
Truncate the file to at most size bytes and return the truncated size.

Size defaults to the current file position, as returned by tell().
The current file position is changed to the value of size.
"""
pass

def writable(self, *args, **kwargs): # real signature unknown
""" True if file was opened in a write mode. """
pass

def write(self, *args, **kwargs): # real signature unknown
"""
Write bytes b to file, return number written.

Only makes one system call, so not all of the data may be written.
The number of bytes actually written is returned. In non-blocking mode,
returns None if the write would block.
"""
pass


程序练习  

程序1: 实现简单的shell sed替换功能

程序2:修改haproxy配置文件
1、查
输入:www.oldboy.org
获取当前backend下的所有记录

2、新建
输入:
arg = {
'bakend': 'www.oldboy.org',
'record':{
'server': '100.1.7.9',
'weight': 20,
'maxconn': 30
}
}

3、删除
输入:
arg = {
'bakend': 'www.oldboy.org',
'record':{
'server': '100.1.7.9',
'weight': 20,
'maxconn': 30
}
}

global
log 127.0.0.1 local2
daemon
maxconn 256
log 127.0.0.1 local2 info
defaults
log global
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
option dontlognull

listen stats :8888
stats enable
stats uri /admin
stats auth admin:1234

frontend oldboy.org
bind 0.0.0.0:80
option httplog
option httpclose
option forwardfor
log global
acl www hdr_reg(host) -i www.oldboy.org
use_backend www.oldboy.org if www

backend www.oldboy.org
server 100.1.7.9 100.1.7.9 weight 20 maxconn 3000

替换文件内容:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray

f = open("yesterday2",'r',encoding="utf-8") # 只读方式打开此文件
f_new = open("yesterday2.bak","w",encoding="utf-8") # 写入方式打开yesterday2.bak文件

for line in f:
if "肆意的快乐等我享受" in line: #找到某句话在line循环中
line = line.replace("肆意的快乐等我享受","肆意的快乐等Donray去享受") #找到某句替换为后面一句
f_new.write(line) #写入到f_new中
f.close() #关闭打开的yesterday2文件
f_new.close() #关闭打开的yesterday2.bak文件

传参方式替换:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray
import sys
f = open("yesterday2",'r',encoding="utf-8") # 只读方式打开此文件
f_new = open("yesterday2.bak","w",encoding="utf-8") # 写入方式打开yesterday2.bak文件

find_str = sys.argv[1] #定义参数,要查找的内容
replace_str = sys.argv[2] #定义参数,要替换的内容

for line in f:
if find_str in line: #找到查找参数在line循环中
line = line.replace(find_str,replace_str) #找到参数对应内容替换为后面一句
f_new.write(line) #写入到f_new中
f.close() #关闭打开的yesterday2文件
f_new.close() #关闭打开的yesterday2.bak文件


with语句

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

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

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

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

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

样例:使用with方式设置变量用as f结尾赋值,本应循环读取的过程,执行一次就结束了
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray
import sys
#f = open("yesterday2",'r',encoding="utf-8") # 只读方式打开此文件
with open("yesterday2","r",encoding="utf-8") as f:
for line in f:
print(line)

还可以用with打开多个文件:
with open('log1') as obj1,open('log2') as obj2:
pass

python官方开发规划,一行代码不要超过80个字符:
打开多个文件建议写法:更为清晰明了
with open("yesterday2","r",encoding="utf-8") as f ,\
open("yesterday2","r",encoding="utf-8") as f2:


字符编码与转码
详细文章:https://www.cnblogs.com/luotianshuai/articles/5735051.html

Unicode:万国码,中英文每字符空间都占2个字节16位
ASCII码不能存中文,每字符占1个字节8位

UTF-8:
英文:按照ASCII码的1字节存储
中文:默认3个字节存储

字符编码发展史:
ASCII 255 1bytes
--> 1980 gb2312 7xxx
--> 1995 GBK1.0 2w+
--> 2000 GB18030 27xxx
--> unicode 2bytes
--> utf-8 en:1bytes,zh:3bytes

GBK转UTF-8格式流程:
1、首先通过编码【decode】转换为Unicode编码
2、然后通过编码【encode】转换为UTF-8编码

样例:python2

#-*- coding:utf-8 -*-

import sys
print(sys.getdefaultencoding()) #打印当前系统编码

s = u"你好" #变量前加u则为unicode编码
print(s) #因为unicode是utf-8的扩展集,因此可直接打印
#s_to_unicode = s.decode("utf-8") #从utf-8解码为unicode
#print(s_to_unicode,type(s_to_unicode)) #打印变量并给出输出type为unicode
s_to_gbk = s.encode("gbk") #从unicode转码为gbk
print (s_to_gbk) #打印转码后的输出,需要把本地远程软件也要改成gbk编码

#gbk_to_utf8 = s_to_gbk.decode("gbk").encode("utf-8")
#print(gbk_to_utf8)


python3样例:
#!/usr/bin/env python
# -*- coding:gbk -*- #声明此程序为gbk字符,但程序内的字符还是需要改编码
# Author:Donray

s = "你好"
s_gbk = s.encode("gbk") #编码为gbk
print(s_gbk) #打印出gbk输出
print(s.encode())

gbk_to_utf8 = s_gbk.decode("gbk").encode("utf-8") #把gbk转成utf-8
print("utf8",gbk_to_utf8) #打印utf-8

print(s.encode("utf-8").decode("utf-8").encode("gb2312").decode("gb2312")) #编码utf8解码utf8再编码gb2312再解码gb2312显示为中文

规则:无论此前是什么编码,先decode解码自己的编码,解码后自然就变为unicode编码,在encode转码为你要更换的编码格式即可

函数基本语法及特性:
http://egon09.blog.51cto.com/9161406/1834777

编程方法:编程规范和方法论
1、面向对象 --> 类 --> class
2、面向过程 --> 过程 --> def #过程就是没有返回值的函数,python中
3、函数式编程 --> 函数 --> def

函数式编程优势:
在一个变化过程中,如果两个变量x和y,并且对于x的每个确定值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,y是x的函数。自变量x的取值范围叫做这个函数的定义域

编程语言中函数定义:函数是逻辑结构化和过程化的一种编程方法。
python中杉树定义方法:
def test(x):
"The function definitions"
x+=1
return x

def:定义函数的关键字
test:函数名
():内可定义形参
"":文档秒数(非必要,但是强烈建议为你的函数添加描述信息)
x+=1:泛指代码块或程序处理逻辑
return:定义返回值

补充:函数式编程就是:先定义一个数学函数,然后按照这个数学模型用编程语言去实现它。

样例:函数和过程
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray
#函数
def func1():
"""testing"""
print('in the func1')
return 0

#过程
def func2():
'''testing2'''
print('in the func2')

x=func1()
y=func2()

print('from func1 return is %s' %x)
print('from func2 return is %s' %y)

为什么使用函数?
没有函数的编程知识在写逻辑(功能),想脱离函数,重用你的逻辑,唯一方法就是拷贝
函数作用:
1、减少重复代码
2、保持一致性
3、变的容易扩展

例一:调用函数简便代码编写
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray

def logger():
with open('a.txt','a+') as f:
f.write('end action\n')

def test1():
print ('test1 starting action... ')

logger()

def test2():
print ('test2 starting action...')

logger()

def test3():
print ('test3 starting action...')

logger()

加时间样例:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray
import time
def logger():
time_format='%Y-%m-%d %X'
time_current=time.strftime(time_format)
with open('a.txt','a+') as f:
f.write('%s end action\n' %time_current)

def test1():
print ('test1 starting action... ')

logger()
def test2():
print ('test2 starting action...')

logger()
def test3():
print ('test3 starting action...')

logger()

函数:当一个函数/过程没有使用return显示定义返回值时,python解释器会隐式 返回none,所以在python中即便是过程也可以算走函数。

函数返回值:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray

def test1():
print('in the test1')

def test2():
print('in the test2')
return 0

def test3():
print('in the test3')
return 1,'hello',['alex','wupeiqi'],{'name':'alex'}

x=test1()
y=test2()
z=test3()
print(x)
print(y)
print(z)

总结:
返回值数=0:返回None
返回值数=1:返回object
返回值数>1:返回tuple一个元组

根据返回值来完成后面的程序该做什么。

函数调用:

调用方法:
1、test()执行,()表示调用函数test,()内可以有参数也可以没有
参数:
1、形参和实参
形参:形式参数,不是实际存在的,是虚拟变量。在定义函数和函数体的时候使用形参,目的是在函数调用时接收实参(实参个数,类型应与实在--对应)

实参:实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给形参

区别:形参是虚拟的,不占用内存空间,形参变量只有在被调用时才分配内存单元,实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参

2、位置参数和关键字(标准调用:实参与形参位置一一对应;关键字调用:位置无需固定)
3、默认参数
4、参数组

例子:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray

def test(x,y): #X,Y为形参
print(x)
print(y)

test(1,2) #1,2为实参,与形参一一对应
test(x=1,y=2) #关键字调用,与形参顺序无关
#混合模式时,关键字必须放在位置参数后面
test(1,y=2)

输出结果:
1
2

默认参数作用:
例子:默认参数,调用参数时默认参数非必传参数,
用途:
1、默认安装值和自定义安装值
2、连接某端口时,可以自定义输入也可以默认输入
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray
def test(x,y=2):
print(x)
print(y)

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

1
3
1
3

参数组:实参数量不固定,如何定义形参?
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray

def test(*args): #*后面未变量名,如此一来可以接受多个实参,多个实参形式一个形参组
print(args)

test(1,2,3,4,5)
#x为实参1,args为后面2-7的元组
def test1(x,*args):
print(x)
print(args)

test1(1,2,3,4,5,6,7)

# **kwargs:把N个关键字,转换为字典的方式
def test2(**kwargs):
print(kwargs)

test2(name='alex',age=8,sex='F')
输出:
{'name': 'alex', 'age': 8, 'sex': 'F'}
#单独显示结果
def test2(**kwargs):
print(kwargs)
print(kwargs['name'])
print(kwargs['age'])
print(kwargs['sex'])

test2(name='alex',age=8,sex='F')
输出:
alex
8
F

#混合模式,参数组一定要放在末尾
def test4(name,age=18,**kwargs):
print(name)
print(age)
print(kwargs)
test4('alex',sex='m',hobby='tesla')
#添加age=8参数
test4('alex',sex='m',hobby='tesla',age=8)
输出结果:
alex
18
{'sex': 'm', 'hobby': 'tesla'}
#age=8后输出,改为定义后的参数
alex
8
{'sex': 'm', 'hobby': 'tesla'}

#*args:接受N个位置参数,转换成元组形式
# **kwargs:把N个关键字,转换为字典的方式
#位置参数不能写在关键字参数后面

局部变量:只在函数中生效的变量
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray

def change_name(name):
print("before change",name)
name = "Donray" #这就是局部变量,这个函数就是这个变量的作用域
print("after change",name)

name = "donray"
change_name(name)
print(name)

也可以声明全局变量,让函数中的变量升级为全局变量
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray

school = "Oldboy Edu"

def change_name(name):
global school #声明全局变量school,后面再打印school变量就可以调用函数内的了,尽量不要这样用,容易出错,如果一定要写,一定在函数外面有个全局变量
school = "Mage Linux"
print("before change",name,school)
name = "Donray"
print("after change",name)

name = "donray"
change_name(name)
print(name)
print(school)

函数内定义的列表、字典、集合、类均会升级为全局变量,只有字符串和整数只在函数生效
school = "Oldboy Edu"
names = ["donray","jack","Rain"]
def change_name():
names[0] = "金角大王"
print("inside func",names)

change_name()
print(names)

全局与局部变量

在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
当全局变量与局部变量同名时:
在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。

递归:
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

递归特性:

1. 必须有一个明确的结束条件

2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少

3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
#例子:n不断除以2
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray

def calc(n):
print(n)
if int(n/2) >0:
return calc(int(n/2))
print("->",n)

calc(10)

函数式编程:

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

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

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

函数式编程语言:通过一堆函数调用得出结果的过程
lisp、hashshell、erlang

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

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Donray
def add(x, y, f):
return f(x) + f(y)

res = add(3, -6, abs) #abs把负数变为正数
print(res)

posted @ 2019-09-26 18:01  donray  Views(122)  Comments(0Edit  收藏  举报