博客参考老师文章:http://www.cnblogs.com/wupeiqi/
函数的理解面向过程:根据业务逻辑从上到下写垒代码
函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
函数作用是你的程序有良好的扩展性、复用性。
同样的功能要是用3次以上的话就建议使用函数。
标注:不能死记,
函数可以理解为一个一个的功能块,你把一个大的功能拆分成一块一块的,用某项功能的时候就去调用某个功能块即可!
函数可以理解为:乐高积木,给你一块一块的,你可以用这些积木块组成你想要的任何,功能!
函数可以调用函数!主函数的作用就是把函数进行串联、调用!函数本身是不能自己执行的如果你不调用就永不执行!
#python name is test.py#-------------------------------deffunc1():passdeffunc2():passdeffunc3():passdeffunc4():
func1()
func2()
func3()if__name__=='__main__'#调用上面的函数,判断了、循环了调用等!#函数里也可以调用函数例子:def func4():#__name__ 这个是用来判断,如果你是把这个程序当模块导入的话他的__name__就等于这个程序的文件名,如果是手动执行这个脚本比如:python test.py 那么__name__ 就等于__main__所以,我们可以用他来做判断,如果你是手动执行我就运行我调函数执行if下面的语句,如果你是调用模块我下面的if判断后面的语句就不执行!仅当模块使用!
#如果函数当模块导入的时候,他导入的是函数的名称,内容没有被导入,当你去调用的时候他才去导入函数里的信息。
自定义函数一、背景
在学习函数之前,一直遵循:面向过程编程,即:根据业务逻辑从上到下实现功能,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,也就是将之前实现的代码块复制到现需功能处,如下
whileTrue:ifcpu利用率 > 90%:#发送邮件提醒连接邮箱服务器
发送邮件
关闭连接if硬盘使用空间 > 90%:#发送邮件提醒连接邮箱服务器
发送邮件
关闭连接if内存占用 > 80%:#发送邮件提醒连接邮箱服务器
发送邮件
关闭连接
上面的代码是就面向过程的编程,但是如果报警多了的话成百的代码需要添加如何操作呢?复制粘贴那会死人的!在看下下面的代码:
def发送邮件(内容)#发送邮件提醒连接邮箱服务器
发送邮件
关闭连接whileTrue:ifcpu利用率 > 90%:
发送邮件('CPU报警')if硬盘使用空间 > 90%:
发送邮件('硬盘报警')if内存占用 > 80%:
第二次必然比第一次的重用性和可读性要好,其实这就是函数式编程和面向过程编程的区别:
面向过程:更具需求一行一行垒代码!逻辑乱、并切代码重复、不易修改重用性差!函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可面向对象:对函数进行分类和封装,让开发“更快更好更强...”二、函数式编程
函数式编程最重要的是增强代码的重用性和可读性:
def函数名(参数):
...
函数体
...
函数的定义主要有如下要点:
def:表示函数的关键字函数名:函数的名称,日后根据函数名调用函数函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...参数:为函数体提供数据返回值:当函数执行完毕后,可以给调用者返回数据。1、返回值
函数是一个功能块,该功能到底执行成功与否,需要通过返回值来告知调用者。
def发送短信():
发送短信的代码...if发送成功:returnTrueelse:returnFalsewhileTrue:#每次执行发送短信函数,都会将返回值自动赋值给result#之后,可以根据result来写日志,或重发等操作result=发送短信()ifresult ==False:
记录日志,短信发送失败...
2、参数
为什么要有参数?看下下面的例子:
如果不定义参数,用函数的话:(每个有相同功能的都写个函数,说好的代码简化呢?)
defCPU报警邮件()#发送邮件提醒连接邮箱服务器
发送邮件
关闭连接def硬盘报警邮件()#发送邮件提醒连接邮箱服务器
发送邮件
关闭连接def内存报警邮件()#发送邮件提醒连接邮箱服务器
发送邮件
关闭连接whileTrue:ifcpu利用率 > 90%:
CPU报警邮件()if硬盘使用空间 > 90%:
硬盘报警邮件()if内存占用 > 80%:
内存报警邮件()
使用函数:(代码明显少了很多,把重复的内用改为参数调用!)
def发送邮件(邮件内容)#发送邮件提醒连接邮箱服务器
发送邮件
关闭连接whileTrue:ifcpu利用率 > 90%:
发送邮件("CPU报警了。")if硬盘使用空间 > 90%:
发送邮件("硬盘报警了。")if内存占用 > 80%:
发送邮件("内存报警了。")
函数的有三中不同的参数:
普通参数默认参数动态参数普通参数:
########## 定义函数 ##########name 叫做函数func的形式参数,简称:形参deffunc(name):PRintname########## 执行函数 ##########'luotianshuai' 叫做函数func的实际参数,简称:实参func('luotianshuai')
但是普通参数有个问题!你在定义参数的时候定义了几个参数,你在调用的时候必须给他几个参数否则就报错!
deffunc(name,shuai):printname,shuai#func('luotianshuai')func('luotianshuai')#报错内容:TypeError: func() takes exactly 2 arguments (1 given)
默认参数:
在你没有给他指定参数的时候他就会使用默认的参数!
deffunc(name, age = 18):print"%s:%s"%(name,age)#指定参数func('luotianshuai', 19)#使用默认参数func('luotianshuai')
注:默认参数需要放在参数列表最后,要不就会报错!原因是:他的参数赋值是一个一个的赋值。如果提供了默认值的形参,你默认一定要往后排序为了就是你给那些没有陪默认值的参数 !
动态参数:
动态参数顾名思义就是可以动态的去扩展函数参数的数量!
例子:1 (多个单个变量,整合成元组)
deffunc(*args):printargs#执行方式一func(11,33,4,4454,5)#输出结果:11,33,4,4454,5#执行方式二li = [11,2,2,3,3,4,54]
func(li)#输出结果:([11,2,2,3,3,4,54])#如果想输入的列表,不想让列表称谓元组里的仅一个元素而是让列表的元素成为元组的元素加*即可func(*li)#输出结果:(11,2,2,3,3,4,54)#############################################################1、接受多个参数
2、内部自动构造元组
3、序列,*,避免内部构造元组
例子:2(整合为字典变量)
deffunc(**kwargs):printargs#执行方式一func(name='luotianshuai',age=18)#执行方式二li = {'name':'luotianshuai', age:18,'gender':'male'}
func(**li)
例子:3(整合了*args,**args)
deffunc(*args, **drgs):printargsprintdargs#例子:func(11,22,33,44,k1='luotianshuai',k2='shuaige')
(11, 22, 33, 44)
{'k2':'shuaige','k1':'luotianshuai'}
扩展:发邮件实例
importsmtplibfromemail.mime.textimportMIMETextfromemail.utilsimportformataddrdefemail(message):
msg= MIMEText("邮件报警测试",'plain','utf-8')
msg['From'] = formataddr(["shuaige",'shuaige@test.com'])#发件人和发件邮箱msg['To'] = formataddr(["帅哥",'451161316@QQ.com'])
msg['Subject'] = message#这里我调用了参数server= smtplib.SMTP("smtp.test.com", 25)
server.login("shuaige@126.com","pwdnq.buzhidao")
server.sendmail('shuaige@126.com', ['451161316@qq.com',], msg.as_string())
server.quit()if__name__== u'__main__':
cpu= 100disk= 500ram= 50foriinrange(1):ifcpu > 90:
alert= u'CPU出问题了'#这里设置了一个变量email(alert)#这里调用函数的时候引用了上面的变量,当执行函数的时候形参讲会被替换掉,message='CPU出问题了' 发送邮件!ifdisk > 90:
alert= u'硬盘出问题了'email(alert)ifram> 80:
alert= u'内存出问题了'email(alert)
内置函数
内置函数:(就是python把各个模块中常用的一些方法给拿出来方便使用)
常用的记住之后,要知道怎么去查:
>>> li = [11,22,33,44]>>> type(li)#查看数据类型<type'list'>
>>> dir(list)#查看类型包含的那些方法>>>help(list)#查看类型中包含的方法的详细说明
函数的作用域看下面的例子:
defsay():
name="tianshuai"printname
say()
这个输出:
tianshuai#是没有问题的,那么看下下面的例子:defsay():
name="tianshuai"printname
say()printname#这个能不能调用呢,不能,会报错!函数的作用域就是在函数里定义的变量不能被外面使用!
在看下面的例子:
name2 ="shuaige"defsay():
name="tianshuai"printnameprintname2
say()
输出结果:
tianshuai
shuaige
总结:函数的作用域就是在函数里定义的变量不能被外面使用!但是外部全局定义的全局变量在函数内是可以使用的。
举个例子来说:你在房子里可以看到屋内的东西和房子歪的东西,但是你在房子外面就只能看到房子外的东西不能看到房子内的东西!
原因防止在函数调用的时候防止变量冲突!
问题:我在外面定义的全局变量在函数内可以改他吗? #看下面的例子:
name2 ="shuaige"defsay():
name="tianshuai"name2="shuaige is shuaige"printname,name2
say()printname2#输出结果:tianshuai shuaigeisshuaige#在函数内改变了shuaige#但是外面调用还是没有改变!
但我就是想在函数里改变全局变量是否可以呢?可以!
#但是我就想在函数内改掉这个变量怎么办呢?在函数内调用global参数!(提供这个功能,但是不建议用!你在局部变量改全局变量很容易引起混乱)name2 ="shuaige"defsay():globalname2
name="tianshuai"name2="shuaige is shuaige"printname,name2
say()printname2
输出结果:
tianshuai shuaigeisshuaige
shuaigeisshuaige
return参数defcount():foriinrange(1,10):ifi = 5:returnelse:printiprint"Hello World"#所以当i=5的时候就直接跳出了函数了,这里是不会被打印出来了!不是循环!!!count()
输出结果:1
2
3
4
return 一般写在函数的末尾,一般你想看函数的执行结果!然后判断后面的程序。看下面的例子
defcount():
name="tianshuai"foriinrange(1,10):ifi == 5:print"hello"else:printireturnname#在这里加了一个returnuser =count()ifuser =="tianshuai":#然后判断,看下执行结果!print"oh shuaige is coming"执行结果:1
2
3
4hello6
7
8
9oh shuaigeiscoming#这里看下! 上面的判断执行了!所以return这个把name的值输出了!
文件操作操作文件时,一般需要经历如下步骤:
打开文件操作文件一、打开文件
文件句柄 = file('文件路径','模式')#python中打开文件有两种方式,即:open(...) 和 file(...) ,本质上前者在内部会调用后者来进行文件操作,推荐使用 open。3.0以后file方法讲被用做其他,open方法会自动的去帮你找他调用得方法在那里!
打开文件时,需要指定文件路径和以何等方式打开文件,打开后,即可获取该文件句柄,日后通过此文件句柄对该文件操作。
打开文件的模式有:
r,只读模式(默认)。w,只写模式。【不可读;不存在则创建;存在则删除内容;】a,追加模式。【可读; 不存在则创建;存在则只追加内容;】"+" 表示可以同时读写某个文件
r+,可读写文件。【可读;可写;可追加】w+,无意义a+,同a"U"表示在读取时,可以将 \r \n \r\n自动转换成 \n (与 r 或 r+ 模式同使用)
rUr+U"b"表示处理二进制文件(如:FTP发送上传ISO镜像文件,linux可忽略,windows处理二进制文件时需标注)
rbwbab二、操作操作
classfile(object):defclose(self):#real signature unknown; restored from __doc__关闭文件"""close() -> None or (perhaps) an integer. Close the file.
Sets data attribute .closed to True. A closed file cannot be used for
further I/OOperations. close() may be called more than once without
error. Some kinds of file objects (for example, opened by popen())
may return an exit status upon closing."""deffileno(self):#real signature unknown; restored from __doc__文件描述符"""fileno() -> integer "file descriptor".
This is needed for lower-level file interfaces, such os.read()."""return0defflush(self):#real signature unknown; restored from __doc__刷新文件内部缓冲区"""flush() -> None. Flush the internal I/O buffer."""passdefisatty(self):#real signature unknown; restored from __doc__判断文件是否是同意tty设备"""isatty() -> true or false. True if the file is connected to a tty device."""returnFalsedefnext(self):#real signature unknown; restored from __doc__获取下一行数据,不存在,则报错"""x.next() -> the next value, or raise StopIteration"""passdefread(self, size=None):#real signature unknown; restored from __doc__读取指定字节数据"""read([size]) -> read at most size bytes, returned as a string.
If the size argument is negative or omitted, read until EOF is reached.
Notice that when in non-blocking mode, less data than what was requested
may be returned, even if no size parameter was given."""passdefreadinto(self):#real signature unknown; restored from __doc__读取到缓冲区,不要用,将被遗弃"""readinto() -> Undocumented. Don't use this; it may go away."""passdefreadline(self, size=None):#real signature unknown; restored from __doc__仅读取一行数据"""readline([size]) -> next line from the file, as a string.
Retain newline. A non-negative size argument limits the maximum
number of bytes to return (an incomplete line may be returned then).
Return an empty string at EOF."""passdefreadlines(self, size=None):#real signature unknown; restored from __doc__读取所有数据,并根据换行保存值列表"""readlines([size]) -> list of strings, each a line from the file.
Call readline() repeatedly and return a list of the lines so read.
The optional size argument, if given, is an approximate bound on the
total number of bytes in the lines returned."""return[]defseek(self, offset, whence=None):#real signature unknown; restored from __doc__指定文件中指针位置"""seek(offset[, whence]) -> None. Move to new file position.
Argument offset is a byte count. Optional argument whence defaults to
0 (offset from start of file, offset should be >= 0); other values are 1
(move relative to current position, positive or negative), and 2 (move
relative to end of file, usually negative, although many platforms allow
seeking beyond the end of a file). If the file is opened in text mode,
only offsets returned by tell() are legal. Use of other offsets causes
undefined behavior.
Note that not all file objects are seekable."""passdeftell(self):#real signature unknown; restored from __doc__获取当前指针位置"""tell() -> current file position, an integer (may be a long integer)."""passdeftruncate(self, size=None):#real signature unknown; restored from __doc__截断数据,仅保留指定之前数据"""truncate([size]) -> None. Truncate the file to at most size bytes.
Size defaults to the current file position, as returned by tell()."""passdefwrite(self, p_str):#real signature unknown; restored from __doc__写内容"""write(str) -> None. Write string str to file.
Note that due to buffering, flush() or close() may be needed before
the file on disk reflects the data written."""passdefwritelines(self, sequence_of_strings):#real signature unknown; restored from __doc__将一个字符串列表写入文件"""writelines(sequence_of_strings) -> None. Write the strings to the file.
Note that newlines are not added. The sequence can be any iterable object
producing strings. This is equivalent to calling write() for each string."""passdefxreadlines(self):#real signature unknown; restored from __doc__可用于逐行读取文件,非全部"""xreadlines() -> returns self.
For backward compatibility. File objects now include the performance
optimizations previously implemented in the xreadlines module."""pass
三、with方法
为了避免打开文件后忘记关闭,可以通过管理上下文,即:(建议使用此方法打开文件)
with open('log','r') as f:
...
如此方式,当with代码块执行完毕时,内部会自动关闭并释放文件资源。
在Python 2.7 后,with又支持同时对多个文件的上下文进行管理,即:
with open('log1') as obj1, open('log2') as obj2:pass
例子:比如要修改nginx.conf 文件然后还的回滚怎么做?
with open('nginx.conf','r') as obj1,open('nginx.conf.new','w') as obj2:foriinobj1.readlines():
i=i.strip()printi
obj2.write(i)
obj2.write('\n')#读取nginx.conf每行然后存储到新的文件nginx.conf.new里!