Python函数

8-29 495 views

一、简述

python函数和其他脚本函数类似,主要解决代码重用性,可读性问题。提高脚本性能和代码可读性。

二、函数定义

python函数定义和其他语言不一样,它是通过def来定义一个函数的,同时它由于没有花括号来定义函数作用域,所以它是通过缩进来定义作用域的。编写时需要注意这点。

例:定一个函数来发送邮件,当发送成功时返回成功信息,当发送失败时返回失败信息。

#coding:utf-8  #强制使用utf-8编码格式
import smtplib #加载smtplib模块
from email.mime.text import MIMEText
from email.utils import formataddr
my_sender='yi_cheng_yu@163.com' #发件人邮箱账号,为了后面易于维护,所以写成了变量
my_user='630885834@qq.com' #收件人邮箱账号,为了后面易于维护,所以写成了变量
def mail():
  ret=True
  try:
    msg=MIMEText('这是一个测试邮件','plain','utf-8')
    msg['From']=formataddr(["来自小易的网易邮箱自动发送",my_sender])  #括号里的对应发件人邮箱昵称、发件人邮箱账号
    msg['To']=formataddr(["如鱼得水",my_user])  #括号里的对应收件人邮箱昵称、收件人邮箱账号
    msg['Subject']="主题:今天天气不错" #邮件的主题,也可以说是标题

    server=smtplib.SMTP("smtp.163.com",25) #发件人邮箱中的SMTP服务器,端口是25
    server.login(my_sender,"******")  #括号中对应的是发件人邮箱账号、邮箱密码(需要注意的是这里的密码不是正真的邮箱密码,而是你开启开启<a href="http://help.163.com/07/0112/11/34KPH9KD007525G1.html">POP3/SMTP/IMAP</a>服务时设置的授权密码)
    server.sendmail(my_sender,[my_user,],msg.as_string())  #括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
    server.quit()  #这句是关闭连接的意思
  except Exception:  #如果try中的语句没有执行,则会执行下面的ret=False
    ret=False
  return ret

ret=mail()
if ret:
  print("邮件发送成功") #如果发送成功则会返回成功信息,稍等20秒左右就可以收到邮件
else:
  print("邮件发送失败") #如果发送失败则会返回失败信息。

需要注意的是函数的return返回值功能,当你不写return时,默认返回的是Noen。如果你写了retrun时,当执行到retrun函数就会返回一个你设定的返回值,同时终止函数(及时你retrun下面还写了其他的代码也是不会执行的)

三、python函数的传参
函数传参都有传形参和传实参的2种方式,顾名思义形参就是形式参数,实参就是实际参数。
例:同时我们还是举上面发邮件的例子,唯一不同的是,这次我们是通过传参方式实现邮件群发功能。

#coding:utf-8  #强制使用utf-8编码格式
import smtplib #加载smtplib模块
from email.mime.text import MIMEText
from email.utils import formataddr
my_sender='yi_cheng_yu@163.com' #发件人邮箱账号,为了后面易于维护,所以写成了变量
def mail(my_user):     #这里的my_user就是形参
  ret=True
  try:
    msg=MIMEText('这是一个测试邮件','plain','utf-8')
    msg['From']=formataddr(["来自小易的网易邮箱自动发送",my_sender])  #括号里的对应发件人邮箱昵称、发件人邮箱账号
    msg['To']=formataddr(["如鱼得水",my_user])  #括号里的对应收件人邮箱昵称、收件人邮箱账号
    msg['Subject']="主题:今天天气不错" #邮件的主题,也可以说是标题

    server=smtplib.SMTP("smtp.163.com",25) #发件人邮箱中的SMTP服务器,端口是25
    server.login(my_sender,"******")  #括号中对应的是发件人邮箱账号、邮箱密码
    server.sendmail(my_sender,[my_user,],msg.as_string())  #括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
    server.quit()  #这句是关闭连接的意思
  except Exception:  #如果try中的语句没有执行,则会执行下面的ret=False
    ret=False
  return ret

ret=mail('yi.chengyu@muchinfo.cn')  #这里的邮箱地址是实参,将实参赋给了形参。所以my_user类似一个变量。
ret=mail('630885834@qq.com')
if ret:
  print("邮件发送成功") #如果发送成功则会返回成功信息,稍等20秒左右就可以收到邮件
else:
  print("邮件发送失败") #如果发送失败则会返回失败信息

传参就是这么简单,下面我再来了解下python的传多个参数和python的默认参数用法

def show(a,b):
print(a,b)
show(1,2)

可以看出传多个参数是很简单的,他们位置默认是一一对应的,分别输出了a和b的值。

def show(a,b=3):
    print(a,b)
show(1)
这个就是将b设置默认参数为3了,当你不传实参的时候,如果不设置默认参数是会报错的,默认参数是可以设置多个的,如C=4, 需要注意的是默认参数必须写在后面,否则将会报语法错误,如:def show(a=1,b=2,c) 这种写法是错误的。

传参默认顺序是一一对应的,但是也可以不一一对应,那就是python的指定参数了。顾名思义,指定参数就是指定某个参数的值,依然值已经被指定了,放置的顺序就可以随意了。下面是一个简单的例子:
def show(a,b):
    print(a,b)
show(b=1,a=2)          #将b的值指定为1,a的值指定为2,就算你b放置在前面效果也是一样的

小知识点(动态参数):将传的参转换为一个元组,只需前面加个*号即可
例:
def t(*n):
    print(n,type(n))
t(114,121,31,31,31,23)

同样将传的参转换为一个字典,只需前面加个**号即可
def t(**n):
    print(n,type(n))
t(yes=114)

两者结合:
def t(*n,**m):
    print(n,type(n),m,tpye(m))
t(114,121,31,31,31,23,ycy='吉安')
前面的自动转换为元组,后面转换为字典


使用动态参数实现字符串格式化--->
1.使用字符格式化
s="{0} is {1}"        #0和1是占位符,通过format方法将其格式化
ret=s.format('xx','2b')  #默认xx对应占位符0,2b对应占位符1
print (ret)      #打印格式化后的字符串效果

xx is 2b     ---执行后的效果

2.使用列表数据格式化
s="{0} is {1}"        #0和1是占位符,通过format方法将其格式化
l=['xx','2b']
ret=s.format(*l)  #使用*号做列表格式化
print (ret)      #打印格式化后的字符串效果
xx is 2b     ---执行后的效果
3.使用字典数据格式化
s="{name} is {actor}"        #key和valu是占位符,通过format方法将其格式化
d={'name':'xx','actor':'2b'}  
ret=s.format(**d)  #使用**将字典数据通过format格式化传入
print (ret)      #打印格式化后的字符串效果
xx is 2b     ---执行后的效果

lambda简单函数表达方式
通过这个表达式,我们能够将简单函数更加简单的表达出来。如:
def fun(a):
    b=a+1
    return b
s=fun(4)
print(s)
这是一个非常简单的函数,看看怎么将其变为lamdba
func = lambda a:a+1         #a是参数,a+1是函数体(函数内部要执行的代码),执行完毕后自动加了return值。
ret = func(4)
print(ret)

python内置函数(直接就可以调用的函数)

上图中的函数都是Python自带的函数。
内置函数具体内容及使用方法 --->

四、模块

说到模块,首先我们来看看一些模块代码的结构,一般都是这样的:

def xxx():
    ................
    ...............
if __name__=='__main__':
    xxx()

这样写的原因是,当你以后这代码打包成模块后,之后模块import导入时不会立马执行,当调用了这函数方法才执行,如:
import *** (*是你模块的名字或者是文件名) 这时候你的代码不会执行
***.xxx() (这是代码是使用***模块下xxx的函数方法,这时候你的代码才会去执行)

自定义模块的导入方法:
我的环境是:centos6.8 Python3.6.1
方法一:函数添加
1 import sys
2 查看sys.path
3 添加sys.path.append("/python/moduleandpacks")

方法二:修改环境变量
用户可以修改系统环境变量PYTHONPATH
方法三:增加.pth文件,推荐使用该方法 在site-packages文件夹下添加一个路径文件,如mypkpath.pth,必须以.pth为后缀,写上你要加入的模块文件所在的目录名称就是了。 # cat /usr/local/python3.6/lib/python3.6/site-packages/mypkpath.pth /python/moduleandpacks 添加完之后可以在sys模块中看到你的自定义模块路径了。 >>> import sys >>> sys.path ['', '/usr/local/python3.6/lib/python36.zip', '/usr/local/python3.6/lib/python3.6', '/usr/local/python3.6/lib/python3.6/lib-dynload', '/usr/local/python3.6/lib/python3.6/site-packages', '/python/moduleandpacks'] 然后将你的.py文件放进/python/moduleandpacks文件夹中,即可使用import导入了,导入之后moduleandpacks文件夹会生成一个名叫__pycache__的文件夹,里面的是对应模块的.pyc编译文件。 在说一个小技巧--->Python使用tab键补齐: 也是在site-packages文件夹下添加一个tab.py文件即可。 cat /usr/local/python3.6/lib/python3.6/site-packages/tab.py
#!/usr/bin/env python 
# python startup file 
import sys
import readline
import rlcompleter
import atexit
import os
# tab completion 
readline.parse_and_bind('tab: complete')
# history file 
histfile = os.path.join(os.environ['HOME'], '.pythonhistory')
try:
 readline.read_history_file(histfile)
except IOError:
 pass
atexit.register(readline.write_history_file, histfile)
del os, histfile, readline, rlcompleter

添加完后即可使用tab键补齐了。

五、装饰器 1.装饰器的存在意义:在不修改函数的情况下用于对函数功能的扩展,特别是批量式的应用,如:你要给100个函数加上运行时间计算 ,或者你要给每个网页都加上验证用户是否登录的功能。这时候你就需要一个装饰器来处理了,简单来说装饰器就是将已有的函数用你自定义些功能的函数给包起来! 注意:不能改变被调用函数内容及功能,不能改变其调用方式 。因为一个函数不可能只有你一个人或者一个程序在调用!

<pre>import time
def insay(a):
    def bao():
        start=time.clock()
        a()
        stop=time.clock()
        print("use",stop-start,"mine")
    return bao
@insay #引用装饰器
def say():
    print ("hello world!")
    time.sleep(0.05)
@insay #引用装饰器
def tell():
    print("aaaaa")
say()        
tell()           #调用函数,可以看出我这调用了2个函数,但是都是用的同一个装饰器。</pre>

上面这个装饰器是由下面这个推来的

<pre>import time
def insay(a):
    def bao():
        start=time.clock()
        a()
        stop=time.clock()
        print("use",stop-start,"mine")
    return bao #return 的bao不加括号,他是不会执行的,就是返回一个函数体。
def say():
    print ("hello world!")
    time.sleep(0.5)
say=insay(say)
say()           #这两行在上面使用简写@insay来使用,其功能是一模一样的 

python参数

一、位置参数 调用函数时根据函数定义的参数位置来传递参数。 #!/usr/bin/env python # coding=utf-8 def print_hello(name, sex): sex_dict = {1...

阅读全文

zabbix–api接口

Zabbix_api4.4官方文档 Zabbix_api3.4中文文档 一、初识api(zabbix4.4.4版本) API(Application Programming Interface,应用程序编程接口)是一些预先定义的...

阅读全文

将配置文件构造成json格式让zabbix自动发现监控项

一、简单介绍 上文我们使用了zabbix的自动发现的监控来监控服务的端口,重点写了zabbix的发现的一个原理和过程,但是实际上我们服务器的配置是比较复杂的,而...

阅读全文

欢迎留言