设为首页 收藏本站
查看: 575|回复: 0

[经验分享] Python之Function

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2016-11-16 15:33:17 | 显示全部楼层 |阅读模式
函数的意义函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内置函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。

函数的定义
  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
  • 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。



def fun(形参):
    "内容"
    return True
fun(实参)
函数调用

定义一个函数只给了函数一个名称,指定了函数里包含的参数,和代码块结构。

这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从Python提示符执行。

最简单的例子


def fun():

    print "OK"

fun()

函数参数定义函数时,申明的是形式参数简称形参,调用函数时,传递的参数是实际参数简称实参。而形参又可以分为四种
  • 必备参数
  • 关键字参数
  • 默认参数
  • 不定长参数

必备参数必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样

def f1(a):
    print "OK"
f1()
def f2(a,b)
    print(a+b)
f2(3+4)
返回结果:OK和7
注:调用必备参数时,必须实参和形参位置对应,否则会报错。
关键字参数 关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。
使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

def info(name,age):
    print "Name %s"%name
    print"Age %s"%age
info("flash",18)
info("aa",19)
输出结果

Name flash
Age 18
Name aa
Age 19
默认参数  调用函数时,缺省参数的值如果没有传入,则被认为是默认值。

def info(name,age,sex="male"):
    print"Name %s"%name
    print "Age %s"%age
    print "Sex %s"%sex
info("flash",18)
info("aa",19,sex="female")
输出结果对比

Name flash
Age 18
Sex male
Name aa
Age 19
Sex female
不定长参数  你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数(又称动态参数),和上述2种参数不同,声明时不会命名。一种是无名名字参数,另一种是有命名参数。

无命名参数(输出的是元组)
def add(*args):
    sum = 0
    for i in args:
        sum += i
    print(sum)
add(1,2,3,4,5)
有命名参数(输出的是字典)
def fun(**kwargs):
    for i in kwargs:
        print "%s:%s"%(i,kwargs)
fun(name="flash",age=22)
Lambda函数lambda函数也叫匿名函数,即,函数没有具体的名称。

f=lambda 赋的参数:参数要做什么
然后调用:f(2)
    def f(x):

        return x**2

    print f(4)

把函数改写成:g=lambda x:x**2

print g(4)
若LAMBDA要跟多个参数,要做什么的参数也要对应
a=range(10)
b=range(10)
g=lambda x,y:x*y,a,b
sorted排序:可以给字典排序
a={'b':4,'a':2,'c':3}
sorted(a.items(),key=lambda x:x[1]) ###items()把字典转换成tuple

map函数:
  map(func, seq1[, seq2,…])
    第一个参数接受一个函数名,后面的参数接受一个或多个可迭代的序列,返回的是一个集合。
        Python函数编程中的map()函数是将func作用于seq中的每一个元素,并将所有的调用的结果作为一个list返回。如果func为None,作用同zip()。

a=range(10)
map(lambda x:x**2,a)#求a的平方
print map(lambda x: x % 2, range(7))
#使用列表解析>>> print [x % 2for x in range(7)][0, 1, 0, 1, 0, 1, 0]
***将元组转换成list***>>> map(int, (1,2,3))[1, 2, 3]***将字符串转换成list***>>> map(int, '1234')[1, 2, 3, 4]***提取字典的key,并将结果存放在一个list中***>>> map(int, {1:2,2:3,3:4})[1, 2, 3]***字符串转换成元组,并将结果以列表的形式返回***>>> map(tuple, 'agdf')[('a',), ('g',), ('d',), ('f',)]#将小写转成大写def u_to_l (s):return s.upper()print map(u_to_l,'asdfd')   

函数返回值 
return语句[表达式]退出函数,选择性地向调用方返回一个表达式。不带参数值的return语句返回None。
  • 函数在执行过程中只要遇到return语句,就会可以停止执行并返回结果,so 也可以理解为 return 语句代表着函数的结束,return 后面的都不会执行的。
  • 如果未在函数中指定return,那这个函数的返回值为None  
  • return多个对象,解释器会把这多个对象组装成一个元组作为一个一个整体结果输出

>>> def sayHi2(**kargs):

...     if kargs.has_key('name'):

...         print kargs['name']

...         print kargs

        return kargs['name']

...

>>> result=sayHi2(name='aa',age=29,phone=222222)

aa

{'phone': 222222, 'age': 29, 'name': 'aa'}

>>> print result

None

若在def 中加return kargs['name'],print result就不会是None


函数作用域一个程序的所有的变量并不是在哪个位置都可以访问的。访问权限决定于这个变量是在哪里赋值的。变量的作用域决定了在哪一部分程序你可以访问哪个特定的变量名称。
大致可以分为四种情况
  • L:local,局部作用域,即函数中定义的变量;
  • E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;
  • G:globa,全局变量,就是模块级别定义的变量;
  • B:built-in,系统固定模块里面的变量,比如int, bytearray等。 搜索变量的优先级顺序依次是:作用域局部>外层作用域>当前模块中的全局>python


total = 0; # 这是一个全局变量
# 可写函数说明
def sum( arg1, arg2 ):
   #返回2个参数的和."
   total = arg1 + arg2; # total在这里是局部变量.
   print "函数内是局部变量 : ", total
   return total;
#调用sum函数
sum( 10, 20 );
print "函数外是全局变量 : ", total
函数递归特性
  • 调用自身函数
  • 有一个结束条件

递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出
举个简单例子,求5的阶乘

def f(i):
    if i == 1:
        return 1
    return i * f(i-1)
print f(5)
小结
  • 使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。
  • 针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。
  • Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。

高阶函数高阶函数英文叫Higher-order function。
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
  • 函数名可以进行赋值
  • 函数名可以作为函数参数,还可以作为函数的返回值

举个例子如

def f(n):
    return n *n
def f1(a,b,f):
    set = f(a) + f(b)
    return set
print f1(1,2,f)<br>返回值为 5
闭包函数 什么是闭包函数,看一个简单的例子

def foo():
    x = 5
    def func():
        print(x)
    return func
foo()()<br>#返回值是5
我们会想,x = 5是属于foo函数的局部变量,为什么可以调用?这就是闭包的闭包的特性。
定义:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。
所以对上述例子中,func()就是闭包函数。
生成器通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

L = [x * x for x in range(10)]#list
g = (x * x for x in range(10))#生成器
生成器保存的是算法,如果调用元素中的只,最好的办法就是使用for循环,因为生成器也是一个可迭代的对象。

g = (x * x for x in range(10))
for n in g:
    print(n)
如果算法过去复杂庞大,我们可以使用函数调用来实现。比如斐波那契数列

def fib(max):
    n, a, b = 0, 0, 1
    while n < max-1:
        #print(b)<br>     yield b
        a, b = b, a + b
        n = n + 1
    return
fib(6)<br>#这就是定义generator的另一种方法。如果一个函数定义中包含<code>yield</code>关键字,那么这个函数就不再是一个普通函数,而是一个generator:
两种方法
  • next(f()) ----计算出一个值注意:生成器在创建的时候已经决定出计算出值的个数,超出next的次数就会报StopIteration
  • send("参数") 传参给yield的变量。注意:第一次不能传参数f().send(None) ==next(f())

迭代器  我们已经知道,可以直接作用于for循环的数据类型有以下几种:
  • 一类是集合数据类型,如list、tuple、dict、set、str等。
  • 一类是generator,包括生成器和带yield的generator function。

  • def  sayHi2(**kargs):

      for i in range(10):
            time.sleep(1)
            yield 'Loop',i
result=sayHi2(name='ma',age=19,phone=222222)
print result.next()
print result.next()
print result.next()
......
满足迭代器协议:
  • 内部有next方法

  • 内部有iter()方法

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
如何去判断一个对象是不是一个可迭代的对象,可以使用内置函数进行判断

>>>from collections import Iterable
>>> isinstance([], Iterable)
True
#如果是返回True,否返回False
注:
  • 凡是可作用于for循环的对象都是Iterable类型;
  • 凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
  • 集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

这里我们也许会问,都已经是可迭代的了,为什么还不是Iterator?这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。 
Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
装饰器什么是装饰器?
装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值也是一个函数对象。本质就是将原函数封装到另外一个函数里面,让其等于一个新函数,在执行新函数的内容。
首先举个简单的例子,在我们事先写好的许多函数中,如果我们想要添加一个新的功能,不可能往每个函数写一遍,这是一个不明智的做法。这里我们就会用到装饰器。例如

import timedef run(func):    def wrapper():        start=time.clock()        func()        end=time.clock()        print 'This function costs',end - start    return wrappersayHi=run(sayHi)sayHi()  ###这2个结合就是等于@run ######import timedef run(func):###接收一个参数,需要被包装的函数    def wrapper():##包装的过程        start=time.clock()        func()        end=time.clock()        print 'This function costs',end - start    return wrapper###返回一个包装的函数体@rundef sayHi():    print 'hellow word'    time.sleep(0.1)def tell():    print "OK"sayHi()tell()######
这是一个最简单的装饰器。其中@符号是python中表示装饰器的语法。
当然装饰器还可以指定参数去更方便的执行例如

import time
def logger(flag = "True"):
    def show_time(f):
        def func():
            start = time.time()
            f()
            end = time.time()
            if flag =="True":
                print("打印日志")
            print(end - start)
        return func
    return show_time
@logger("true")
def foo1():
    print("OK!!!!!!!!!!!!!")
    time.sleep(1)
foo1()
def foo2():
    print("OK!!!!!!!!!!!!!")
    time.sleep(2)
foo2()
也可以传入不定长参数做简单的计算

import time
def show_time(f):
    def func(*args,**kwargs):
        start = time.time()
        f(*args,**kwargs)
        end = time.time()
        print(end - start)
    return func
@show_time
def foo1(*args,**kwargs):
    Sum = 0
    for i in args:
        Sum += i
    print(Sum)
    time.sleep(1)
foo1(1,2,3)
内置函数:
abs(n)

    divmod(a,b)##趣商的余数 divmod(8,2)-->(4,0)

pow(a,b)幂

    round(a)#4舍5入
    sum(list)#LIST的值相加

小结:
在面向对象(OOP)的设计模式中,decorator被称为装饰模式。OOP的装饰模式需要通过继承和组合来实现,而Python除了能支持OOP的decorator外,直接从语法层次支持decorator。Python的decorator可以用函数实现,也可以用类实现。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-301176-1-1.html 上篇帖子: Python 第三方模块pythonnmap来实现高效的端口扫描 下篇帖子: python批量修改SecureCRT会话密码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表