码迷,mamicode.com
首页 > 编程语言 > 详细

Python自动化运维之3、初识函数及lambda

时间:2016-08-06 00:35:13      阅读:444      评论:0      收藏:0      [点我收藏+]

标签:

函数

函数的基础概念:
  函数是python为了代码最大程度地重用和最小化代码冗余而提供的基本结构
  函数是一种设计工具,它能让程序员将复杂的系统分解为可管理的部件
  函数用于将相关功能打包并参数化
  在python中可以创建4种函数
    (1)全局函数:定义在模块
    (2)局部函数:嵌套于其它函数中
    (3)lambda函数:表达式,如需多次调用
    (4)方法:与特定数据类型关联的函数,并且只能与数据类型关联一起使用
  python提供了很多内置函数


创建函数:

def functionName(arg1,arg2,...):
  suite
   return 

函数的定义主要有如下要点:

  • def:表示函数的关键字
  • 函数名:函数的名称,日后根据函数名调用函数
  • 函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...
  • 参数:为函数体提供数据
  • 返回值:当函数执行完毕后,可以给调用者返回数据。

一些相关的概念:
  def是一个可执行语句
    因此可以出现在任何能够使用语句的地方,甚至可以嵌套于其他语句,例如if或while中
  def创建了一个对象并将其赋值给一个变量名(即函数名),函数体则存在内存
  return用于返回结果对象,其为可选;无return语句的函数自动返回None对象
    返回多个值时,彼此间使用逗号分隔,且组合为元组形式返回一个对象
    函数一旦执行到return,函数就终止了,如果return下面还有执行语句则终止
  def语句运行之后,可以在程序中通过函数后附加()进行调用

函数作用域:
  python创建、改变或查找变量名都是在名称空间中进行
  在代码中变量名被赋值的位置决定了其能被访问到的范围
  函数定义了本地作用域,而模块定义了全局作用域

    1.全局变量全部用大写表示
    2.全局变量都可以被访问,函数内部的变量则为本地作用域
    3.在函数内如果要修改全局变量,需要global
    4.特殊:字典,列表可以在函数内修改,但是不能重新赋值

NAME = tomcat

def f1():
    age = 18
    global NAME
    NAME = xiao
    print(age,NAME)

def f2():
    age = 27
    print(age,NAME)

f1()
f2()

函数的参数:
  默认情况下,参数通过其位置进行传递,从左至右,这意味着,必须精确地传递和函数头部参数一样多的参数
  但也可以通过关键字参数、默认参数或参数容器等改变这种机制
    (1)普通参数:定义函数时从左至右
    (2)默认参数:定义函数时是使用"name=value"的语法直接给变量一个值,从而传入的值可以少于参数个数
    (3)指定参数:调用函数时指定"name形式参数=value实际参数"的语法通过参数名进行匹配
    (4)动态参数:定义函数时形式参数中收集任意多基于普通参数
      定义函数时使用* :收集普通参数,返回元组,*args
      定义函数时使用**:收集指定参数,返回列表,**kwargs
    (5)动态参数解包:调用函数时,使用**开头的参数,从而传递任意多基于普通或指定参数

注意:定义函数时
  1.混用普通参数和默认参数,应当把默认参数写到右侧
  2.混用有默认和无默认值的参数时,无默认值放左侧

 

1、返回值

函数是一个功能块,该功能到底执行成功与否,需要通过返回值来告知调用者。

以上要点中,比较重要有参数和返回值:

def 发送短信():
       
    发送短信的代码...
   
    if 发送成功:
        return True
    else:
        return False
   
while True:
       
    # 每次执行发送短信函数,都会将返回值自动赋值给result
    # 之后,可以根据result来写日志,或重发等操作
   
    result = 发送短信()
    if result == False:
        记录日志,短信发送失败...

2、参数

没有参数的情况

#!/usr/bin/env python
# -*- coding:utf-8 -*-

‘‘‘
1.需要开启邮箱服务sendmail
2.邮箱服务器需要开启SMTP服务
‘‘‘

def sendmail():
    try:
        import smtplib
        from email.mime.text import MIMEText
        from email.utils import formataddr

        msg = MIMEText(邮件内容, plain, utf-8)
        msg[From] = formataddr(["发件人", pythonxiao@126.com])
        msg[To] = formataddr(["收件人", 329275108@qq.com])
        msg[Subject] = "邮件主题"

        server = smtplib.SMTP("smtp.126.com", 25)
        server.login("pythonxiao@126.com", "xiaozhiqi2016")
        server.sendmail(pythonxiao@126.com, [329275108@qq.com, ], msg.as_string())
        server.quit()
    except:
        return "失败"
    else:
        return cc

ret = sendmail(msg)
if ret == cc:
    print("发送成功")
else:
    print("发送失败")

有参数的情况:

#!/usr/bin/env python
# -*- coding:utf-8 -*-

def sendmail(email,content):
    try:
        import smtplib
        from email.mime.text import MIMEText
        from email.utils import formataddr

        msg = MIMEText(content, plain, utf-8)
        msg[From] = formataddr(["发件人", pythonxiao@126.com])
        msg[To] = formataddr(["收件人", 329275108@qq.com])
        msg[Subject] = "邮件主题"

        server = smtplib.SMTP("smtp.126.com", 25)
        server.login("pythonxiao@126.com", "xiaozhiqi2016")
        server.sendmail(pythonxiao@126.com, [email, ], msg.as_string())
        server.quit()
    except:
        return "失败"
    else:
        return cc

while True:
    msg = input("请输入邮箱地址:")

    #实际参数
    ret = sendmail(msg,"SB")
    if ret == cc:
        print("发送成功")
        break
    else:
        print("发送失败")

从上面例子可以看出有参数的函数表现的非常灵活可扩展!

函数的有三中不同的参数(定义函数时):

  • 普通参数
  • 默认参数
  • 动态参数

  指定参数和动态参数解包是发生在调用函数

技术分享
(1)# xxoo为普通参数也叫形式参数,简称:形参
def f1(name):
    print(name)

# ‘test‘ 叫做函数的实际参数,简称:实参
f1(tomcat)
普通参数
技术分享
(2)# name 是普通参数,ab=5是默认参数
def f1(name,ab=5):
    print(name,ab)

# 指定参数
f1(tomcat,12)

# 使用默认参数
f1(tomcat)

注意:默认参数需要放在参数列表最后
默认参数
技术分享
(3)# 动态参数(1):*args 返回的是一个元组
def f1(*args):
    print(args,type(args))

# 执行方式一    
f1(11)

# 如果传入一个列表,则这个列表是当作元组中的一个元素
li = [a,b,c]
f1(li)

# 执行方式二:执行函数时有*,把所有迭代对象拆分为单个元素作为元组的元素,如传入列表,会把列表中每一个元素遍历添加到元组中当作一个元素
f1(*l1)
动态参数一
技术分享
(4)#动态参数(2):**kwargs 返回的是一个字典
def f1(**kwargs):
    print(args,type(args))
    
# 执行方式一:只能传入指定参数    
f1(n1=alex,n2=18)

dic = {k1:v1,k2:v2}
f1(kk=dic)

# 执行方式二:实际参数如果有**,传入的应该是一个字典,会把每一对键值对像不带**一样把指定参数传入函数中
f1(**dic)
动态参数二
技术分享
(5)# 俗称万能参数
def f1(*args,**kwargs):
    print(args,type(args))
    print(kwargs,type(kwargs))

# 执行方式一
f1(11,22,33,k1=v1,k2=v2)

# 执行方式二
l1 = [1,2,3,4]
d1 = {a:xiao,b:zhi,c:qi}
f1(*l1,**d1)
俗称万能参数

在python中可以经常看到万能参数,比如str.format()用于格式化的方法,这里用不同的参数传递方式实现相同的效果

>>> s1 = i am {0}, age {1}.format(alex,18)
>>> print(s1)
i am alex, age 18

>>> s2 = i am {0}, age {1}.format(*[alex,18])
>>> print(s2)
i am alex, age 18

>>> s3 = i am {0}, age {1}.format(*(alex,18))
>>> print(s3)
i am alex, age 18

>>> s4 = i am {name}, age {age}.format(name=alex,age=18)
>>> print(s4)
i am alex, age 18

>>> dic = {name:alex,age:18}
>>> s5 = i am {name}, age {age}.format(**dic)
>>> print(s5)
i am alex, age 18

3.补充:

(1).在定义相同函数时,后一个函数名会指向新的内存对象,函数名是函数体在内存中的引用,就像变量赋值一样,变量名是对对象在内存中的引用

def f1(a,b):
    return a + b

def f1(a,b):
    return a * b

ret = f1(8,8)
print(ret)

(2).函数在传递参数的时候是内存中的引用,而不是复制,所以下面的例子中a1和l1都会改变

def f1(a1):
    a1.append(999)

l1 = [1,2,3,4]
f1(l1)

print(l1)

 

函数式编程:

以后写函数按照下面这个例子来编写,规范,这是一个登录注册的编程

#!/usr/bin/env python
# -*- coding:utf-8 -*-


def login(username,password):
    """
    用于用户登陆
    :param username: 用户输入的用户名
    :param password: 用户输入的密码
    :return: true表示成功,false表示失败
    """

    f = open(db,r)
    for line in f:
        line_list = line.strip().split(|)
        if line_list[0] == username and line_list[1] == password:
            return True

    return False


def register(username,password):
    """
    用于用户注册
    :param username: 用户名
    :param password: 密码
    :return: 默认返回None
    """

    f = open(db,a)
    temp = \n + username + | + password
    f.write(temp)
    f.close()


def main():
    t = input("1: 登陆;2: 注册")
    if t == 1:
        user = input(请输入用户名:)
        pwd = input(请输入密码:)
        r = login(user,pwd)
        if r:
            print(登陆成功)
        else:
            print(登陆失败)

    elif t == 2:
        user = input(请输入用户名:)
        pwd = input(请输入密码:)
        register(user,pwd)
        print(注册成功)


main()

 

三元运算符  

  三目运算符可以简化条件语句的缩写,可以使代码看起来更加简洁,三目可以简单的理解为有三个变量,它的形式是这样的 name= k1 if 条件 else k2 ,如果条件成立,则 name=k1,否则name=k2,下面从代码里面来加深一下理解,从下面的代码明显可以看出三目运算符可以使代码更加简洁。

a=1
b=2
if a<b:                     #一般条件语句的写法
    k=a
else:
    k=b
     
c=a if a<b else b         #三目运算符的写法,如果a<b为True,则c=a,否则c=b

 

lambda表达式

对于简单的函数,也存在一种简便的表示方式,即:lambda表达式

# ###################### 普通函数 ######################
# 定义函数(普通方式)
def func(arg):
    return arg + 1
    
# 执行函数
result = func(123)
    
# ###################### lambda ######################
    
# 定义函数(lambda表达式)
my_lambda = lambda arg : arg + 1
    
# 执行函数
result = my_lambda(123)

 

练习:

1、简述普通参数、指定参数、默认参数、动态参数的区别  

  普通参数传递的个数和顺序要明确,默认参数传递的时候,如果没有给默认参数复制的话,会使用默认值,如果给定了的话,就会使用给定值。动态参数的个数不确定,可以传递任意个参数,这些参数自动组装成一个元组,可以在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去,指定参数传递的是一个明确的类似键值,这些参数自动组装成一个字典,可以先定义一个字典,在前面加上**变成关键字参数传给函数。

2、写函数,计算传入字符串中【数字】、【字母】、【空格] 以及 【其他】的个数 

def fun(s):
    digitnum, alphanum, sapcenum, othernum=0,0,0,0
    for i in s:
        if i.isdigit():
            digitnum+=1
        elif i.isalpha():
            alphanum+=1
        elif i.isspace():
            sapcenum+=1
        else:
            othernum+=1
    return (digitnum,alphanum,sapcenum,othernum)

3、写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5  

def fun(s):
    ret=False
    if isinstance(s,str) or isinstance(s,str) or isinstance(s,tuple):
       if len(s)>5:
           ret=True
    return ret

4、写函数,检查用户传入的对象(字符串、列表、元组)的每一个元素是否含有空内容

def fun(s):
    ret=False
    if isinstance(s, str) or isinstance(s, str) or isinstance(s, tuple):
        for i in s:
           if i==‘‘:
               ret=True
               break
    return ret

5、写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。

def fun(s):
    if isinstance(s,list):
        if len(s)>2:
            return s[0:2]
    return None

6、写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者。

def fun(s):
    if isinstance(s,list) or isinstance(s,tuple):
        l=[]
        for i in range(1,len(s),2):
            l.append(s[i])
        return l
    return None

7、写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。

def fun(s):
    if isinstance(s,dict):
        for i in s:
            if len(s[i])>2:
                s[i]=s[i][0:2]
    return s

8、写函数,利用递归获取斐波那契数列中的第 10 个数,并将该值返回给调用者。

def fun(n):
    if 1==n :
        return 0
    elif 2==n:
        return 1
    else:
        return fun(n-1)+fun(n-2)

 

Python自动化运维之3、初识函数及lambda

标签:

原文地址:http://www.cnblogs.com/xiaozhiqi/p/5742973.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!