python基础-函数

本文详细介绍了Python中的函数,包括函数定义、调用、默认参数、关键字参数的使用,以及lambda函数和动态函数的创建。此外,重点讨论了生成器函数的概念和优势,如何利用yield实现高效内存利用。最后,提到了偏函数的应用,通过functools模块实现函数与参数的预绑定。

函数

函数的作用是将一坨代码组合到一起实现一个功能,并且可以复用,以简化代码,节省人力。

def functionName(param):
    process

函数的定义格式如上

def greet():
    print('welcome to python')
greet()

函数的调用采用的方式是函数名称+(),函数名存放的是对函数对象的引用,所以我们也可以赋值给其它变量.
如:

def greet():
    print('welcome to python')
g = greet
g()

上述代码将greet赋值给g,g()也会打印相同的结果

def greet():
    print('welcome to python')
def hello():
    print('hwllo,python')
def world():
    print('world,python')

list = [greet,hello,world]
for x in list:
    x();
输出:
welcome to python
hwllo,python
world,python

很显然,我们可以将函数名称组成一个列表,然后遍历调用

def sum(x,y,z=1):
    return x+y+z
num = sum(1,2)
print(num)

输出:4

上述我们把z的值默认等于了1,因此sum()函数只需传两个参数即可。


def sum(x=1,y,z):
    return x+y+z
num = sum(1,2)
print(num)

输出:    def sum(x=1,y,z):
           ^
SyntaxError: non-default argument follows default argument

python不允许不带默认参数的参数跟随一个带有默认参数的参数的后面。可以想象,如果sum(1,2)的话,1的值是给x还是给y呢?

def frange(arg0,arg1=None,arg2=None):
    '''类似于range()的浮点数生成器'''
    start = 0.0
    inc = 1.0
    if arg2 is not None: #3个参数均有
        start = arg0
        stop = arg1
        inc = arg2
    elif arg1 is not None:#给定2个参数
        start = arg0
        stop = arg1
    else:                 #给定1个参数
        stop = arg0
    result = []
    while start <(stop-(inc/2.0)):
        result.append(start)
        start+=inc
    return result

res = frange(3.0,5,1.0)
print(res)

#res [3.0, 4.0]

上述的代码是默认参数应用的例子,如果给定3个参数,第一个为开始,第二个为结束,第三个为步长。
”’文档”’ ,三个单引号或者三个双引号之间的为文档注释,它存在的意义是给定一个简单的总结说明。
可以看到,比较的时候用的is not None,而不是 !=None,在python中None的实例只有一个,因此,所有None的id(None)值都是一样的,is 比较的是地址,而!=None比较的是值,比较地址相对于从地址中取值再比较的速度是有优势的。
参数传递的都是对象的引用,但是因为字符串和整数的变量是不可变的,一个不可变参数的值在函数内发生了改变,该参数就会绑定到一个新的对象上,而它原先引用的对象则不会发生改变。
返回值和java不同的是,无需给定指定的类型,可以显式的return。非显式的就会返回None.

生成器函数

def frange(arg0,arg1=None,arg2=None):
    '''类似于range()的浮点数生成器'''
    start = 0.0
    inc = 1.0
    if arg2 is not None: #给定3个参数        
        start = arg0
        stop = arg1
        inc = arg2
    elif arg1 is not None:#给定2个参数
        start = arg0
        stop = arg1
    else:                 #给定1个参数
        stop = arg0
    result = []
    while start <(stop-(inc/2.0)):
        yield start
        start+=inc

res = frange(3.0,5.0,1.0)
print(res)
for x in res:
    print(x)

输出:
<generator object frange at 0x02BA7F80>
3.0
4.0

把return换成yield,就可以把函数转换成一个生成器。对于长列表,使用生成器的这种形式会更效率些,因为使用列表的那种形式会在内存中创建整个列表,而生成器每次只创建一个元素。yield和return语句比较相似,有个不同的是yield会接着上次的状态继续执行,如yield第一次返回是3.0,第二次返回的是4.0,那么3.0的状态依然存在。于是这个生产器包含的值是3.0和4.0.

res = frange(3.0,5.0,1.0)
print(res)
print(next(res))
print(next(res))
print(next(res))

输出:

res生成器中有3.0 4.0 ,当输出4.0后再次next(),就会报StopIteration异常。

res = frange(3.0,5.0,1.0)
for x in res:
    print(x)
res = frange(3.0,5.0,1.0)
resl = list(res)
print(resl)

输出:
[3.0, 4.0]
[3.0, 4.0]

可以看到,列表的构造函数和for循环可以自动处理StopIteration异常

关键字参数的使用

def simplify(text, space=" \t\r\n\f", delete=""):
    result = []
    word = ""
    for char in text:  # 遍历text
        if char in delete:  # 判断字符是否在delete中 如果在则跳出本层循环
            continue
        elif char in space:  # 判断是否在space
            if word:  # 如果word存在
                result.append(word)  # 将word添加到列表
                word = ""
        else:
            word += char  # 即不在delete,也不在space,拼接到word
    if word:
        result.append(word)
    return " ".join(result)

print(simplify(' this   and\n that\t too')) #this and that too)
print(simplify(" Hello. world ",delete="."))#Hello world
print(simplify(delete="aed",text="sdeja")) #s j

上述代码的含义是去掉给定字符串的空格,或者指定需要删除的字符,在第一个调用中,simplify(’ this and\n that\t too’))我们使用了默认的space和delete参数,第二个调用中我们指定了一个关键字参数delete,使用了space默认参数,第三个调用我们给定两个关键字参数。可以看出,如果使用关键字参数,其参数的顺序由自己决定,但是如果使用了位置参数,那么位置参数的顺序要放在关键字参数的前面,如例二。

lambda函数

function = lambda x:pow(x,3)
print(function(2)) #8

lambda用来创建简单的匿名函数,它不能包含分支也不能包含循环,也没有return语句,其返回值仅仅是表达式计算后得到的值。如上述的代码就是计算x的3次方的值。

动态函数的创建

import sys
if sys.version_info[:2]<(2,4):
    def sorted(items):
        items = list(items)
        items.sort()
        return items

这段代码的含义是当python解释器的版本在2.4以下时,定义一个sorted()函数,因为sorted()函数是在python2.4中加入的。
sys.version_info是一个元组,其保存了当前使用的python解释器的版本,如:sys.version_info(major=3, minor=4, micro=4, releaselevel=’final’, serial=0),我目前使用的版本是3.4.4,[:2]是切片的操作,截取前两个元素与(2,4)比较,这里需要注意的是元组可以进行比较的操作,但前提是元组里面的元素可以比较。看下面这段代码:

print((2,3)<(4,5)) #True
print((2,3)<(1,4)) #False
print((2,3)<(1,2)) #False

上述的比较类似于 2<3 and 3<5 ,必须都满足条件返回的才是True.

偏函数

#偏函数的应用
def hello(who):
    print('hello',who)
hello('me') #hello me

上述的代码,传进一个参数,并打印,现在我只想向自己问好,也就是说,我们确定了参数的值为me,现在想把函数和参数都封装到一起,组成一个可调用的对象,那么该如何改造呢?

def partial(func,arg):
    def callme():
        return func(arg)
    return callme

def hello(who):
    print('hello',who)

f1=partial(hello,'me')
f1()

输出:hello me

partial有两个参数,一个是要调用的函数的引用,一个是要调用函数的参数。在上面的例子中,partial(hello,’me’)返回相当于返回的是hello(‘me’)的hello.传给f1,f1()调用.

import functools
def hello(who):
    print('hello',who)

f1=functools.partial(hello,'me');

输出:hello me

这里python为我们提供了一个工具functools,可以直接实现函数和参数绑定的操作

总结:

  1. 我们讲了函数的定义,def f(参数1,参数2,...),f中存储的是函数对象的引用,f()加个括号为调用该函数,我们也可以这样操作g=f;g(),这样也可以调用函数。

  2. 默认参数,def f(参数1,参数2=2),默认参数存在的情况下,调用函数可以只传不带默认参数的值,如f(1),这里需要注意的是,定义带默认值的函数时,带默认值的参数要放在不带默认值参数的后面。

  3. is not None,is not比较的是内存中的地址,==比较的是地址中的值,比较地址比比较值要快一些,因为比较值要先从地址中取值。None对象是全局变量,在python中只存在一个。

  4. 生成器函数, 将函数中的return换成yield就可,生成器的优点在于可以不用一次性生成很多值来占用内存,并且在需要的时候才会生成对应的值。生成器遍历完成再次next()会出现stopIteration异常,欣慰的是for循环和list的构造函数可以自动的处理它。

  5. 关键字参数是将参数名+参数值传给函数,如def f(a,b) 调用的时候这样传参 f(b=2,a=1),关键字参数间可以随意的更改参数的位置,如f(a=1,b=2),但是如果有位置参数的话,关键字参数要放在位置参数的后面。

  6. 匿名函数用关键字lambda来定义,它只能有一些简单的语句,不能包含return ,循环,分支结构。f=lambda x:pow(x,3)

  7. 动态函数的创建:动态函数就是在某些条件满足的条件下,再创建函数

  8. 偏函数:我们想让函数和其参数绑定起来,python提供的工具functools.partial(func,param)可以实现这一要求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值