当前位置 : 主页 > 手机开发 > harmonyos >

python学习笔记(3)

来源:互联网 收集:自由互联 发布时间:2023-08-26
43、函数(1)若函数没有返回值,则默认的返回值是None(2)装饰器装饰器实际就是函数,它接受函数对象。我们在执行函数之前,可以运行些预备代码,也可以在执行代码之后做些清


43、函数

(1)若函数没有返回值,则默认的返回值是None

(2)装饰器

装饰器实际就是函数,它接受函数对象。我们在执行函数之前,可以运行些预备代码,也可以在执行代码之后做些清理工作。这类似于java中的AOP,即面向切面编程,可以考虑在装饰器中置入通用功能的代码来降低程序复杂度。例如,可以用装饰器来:引入日志、增加计时逻辑来检测性能、给函数加入事务的能力

1. 无参装饰器:
@deco2
@deco1
def func(arg1, arg2, ...): 
    pass

这和创建一个组合函数是等价的:

def func(arg1, arg2, ...):
    pass
func = deco2(deco1(func))

2. 有参装饰器:
@deco1(deco_arg)
@deco2
def func():
    pass

这等价于:

func = deco1(deco_arg)(deco2(func))

示例:
from time import ctime,sleep

def tsfunc(func):
    def wrappedFunc():
        print '[%s] %s() called' % (ctime(), func.__name__)
        return func()
    return wrappedFunc

@tsfunc
def foo():
    print 'foo() is invoked !'

foo()
sleep(4)

for i in range(2):
    sleep(1)
    foo()

运行结果:
[Tue Jul 17 22:45:54 2012] foo() called
foo() is invoked !
[Tue Jul 17 22:45:59 2012] foo() called
foo() is invoked !
[Tue Jul 17 22:46:00 2012] foo() called
foo() is invoked !


(3)传递函数
函数也是phthon对象的一种,也是一个对象,也可以将函数对象的引用赋值给一个变量,通过这个变量,也相当于是这个函数的别名,来调用这个函数,基于这种机制,就有了传递函数,即可以将一个函数名通过形参传递给另外一个函数,在这个函数中调用传递进来的函数。如下示例:

>>> def foo():
	print 'in foo()'

>>> bar=foo
>>> bar()
in foo()

>>> def bar(argfunc):
	argfunc()
	
>>> bar(foo)
in foo()
>>> 

(4)可变长度的参数
于函数调用提供了关键字以及非关键字两种参数类型,python 用两种方法来支持变长参数,在函数调用中使用*和**符号来指定元组和字典的元素作为非关键字以及关键字参数的方法。

1. 非关键字可变长参数(元组)
可变长的参数元组必须在位置和默认参数之后,带元组(或者非关键字可变长参数)的函数普遍的语法如下:
def function_name([formal_args,] *vargs_tuple):pass

星号操作符之后的形参将作为元组传递给函数,元组保存了所有传递给函数的"额外"的参数(匹
配了所有位置和具名参数后剩余的)。如果没有给出额外的参数,元组为空。

之前,只要在函数调用时给出不正确的函数参数数目,就会产生一个TypeError异常。通过末尾增加一个可变的参数列表变量,我们就能处理当超出数目的参数被传入函数的情形,因为所有的额外(非关键字)参数会被添加到变量参数元组。

示例:
>>> def tupleVarArgs(arg1,arg2='defaultB',*rest):
	print 'formal arg1: ',arg1
	print 'formal arg2: ',arg2
	for eachXarg in rest:
	    print 'another arg: ',eachXarg

>>> tupleVarArgs('abc')
formal arg1:  abc
formal arg2:  defaultB

>>> tupleVarArgs('abc',25.0)
formal arg1:  abc
formal arg2:  25.0

>>> tupleVarArgs('abc',25.0,'suo','piao',999999L)
formal arg1:  abc
formal arg2:  25.0
another arg:  suo
another arg:  piao
another arg:  999999


精要:多余的参数保存到一个元组中,传递给函数

2.关键字变量参数(Dictionary)
语法:def function_name([formal_args,][*vargst,] **vargsd):pass

示例:
>>> def dicVarArgs(arg1,arg2='defaultB',**rest):
	print 'formal arg1: ',arg1
	print 'formal arg2: ',arg2
	for key in rest:
	    print 'xtra arg %s: %s ' % (key,rest[key])

	    
>>> dicVarArgs('abc')
formal arg1:  abc
formal arg2:  defaultB

>>> dicVarArgs('abc',123)
formal arg1:  abc
formal arg2:  123

>>> dicVarArgs('abc',123,c='suo',d=456,e=9999L)
formal arg1:  abc
formal arg2:  123
xtra arg c: suo 
xtra arg e: 9999 
xtra arg d: 456 
>>> 


精要:多余的关键字参数,将其放到字典中,传递给函数

关键字和非关键字可变长参数都有可能用在同一个函数中,只要关键字字典是最后一个参数并且非关键字元组先于它之前出现,如下示例:

>>> def varArgs(arg1,arg2='defaultB',*tupleRest,**dicRest):
	print 'formal arg1: ',arg1
	print 'formal arg2: ',arg2
	for each in tupleRest:
		print 'non-key arg: ',each
	for key in dicRest:
	    print 'xtra arg %s: %s ' % (key,dicRest[key])

>>> varArgs('abc')
formal arg1:  abc
formal arg2:  defaultB

>>> varArgs('abc',123)
formal arg1:  abc
formal arg2:  123

>>> varArgs('abc',123,'suo',456,c='piao',d='love',e=9999)
formal arg1:  abc
formal arg2:  123
non-key arg:  suo
non-key arg:  456
xtra arg c: piao 
xtra arg e: 9999 
xtra arg d: love 

其实,也可以这样来调用带有可变长参数的函数:
>>> mytuple=('suo','love','piao',9999)
>>> mydic={'c':'how','d':'are','e':'you','f':88888L}
>>> varArgs('abc',123,*mytuple,**mydic)
formal arg1:  abc
formal arg2:  123
non-key arg:  suo
non-key arg:  love
non-key arg:  piao
non-key arg:  9999
xtra arg c: how 
xtra arg e: you 
xtra arg d: are 
xtra arg f: 88888 
>>> 
这样的调用,更加清晰一些。

(5)函数式编程
1. lambda 匿名函数
python 允许用lambda 关键字创造匿名函数,语法为:
lambda [arg1[, arg2, ... argN]]: expression

lambda必须放在一行中,就像是单行版的函数一样,但应该叫它lambda表达式

它返回一个函数对象,这个函数执行的操作,就是expression中的内容

示例:
>>> a=lambda x,y=2:x+y
>>> a(4)
6
>>> b=lambda *z : z
>>> b(1,2,3)
(1, 2, 3)

虽然看起来lambdda 是一个函数的单行版本,但是它不等同于c++的内联语句,这种语句的目的是由于性能的原因,在调用时绕过函数的栈分配。lambda 表达式运作起来就像一个函数,当被调用时,创建一个框架对象。


2.内建函数
apply(func[, nkw][, kw]):
用可选的参数来调用func,nkw 为非关键字参数,kw 关键字参数;返回值是函数调用的返回值。

filter(func, seq):
调用一个布尔函数func 来迭代遍历每个seq 中的元素; 返回一个使func 返回值为ture 的元素的序列

map(func, seq1[,seq2...]):
将函数func 作用于给定序列(s)的每个元素,并用一个列表来提供返回值;如果func 为None, func 表现为一个身份函数,返回一个含有每个序列中元素集合的n 个元组的列表。

reduce(func, seq[, init]):
将二元函数作用于seq 序列的元素,每次携带一对(先前的结果以及下一个序列元素),连续的将现有的结果和下雨给值作用在获得的随后的结果上,最后减少我们的序列为一个单一的返回值;如果初始值init 给定,第一个比较会是init 和第一个序列元素而不是序列的头两个元素。


(6)变量作用域
当搜索一个标识符的时候,python 先从局部作用域开始搜索。如果在局部作用域内没有找到那
个名字,那么就一定会在全局域找到这个变量否则就会被抛出NameError 异常。

问题引出:
在函数中定义了一个局部的bar变量,在主函数体中,定义了一个全局的bar变量,但是有可能在函数体内的bar变量会覆盖掉全局的bar变量,这样全局的bar变量在函数体内就失效了。。

如下示例:
bar=100

def foo():
    print 'calling foo()...'
    bar=200
    print 'in foo(), bar is ', bar


print 'bar=',bar
foo()
print 'bar=',bar

运行结果如下:
bar= 100
calling foo()...
in foo(), bar is  200
bar= 100

问题解决:
为了解决上面的问题,我们可以使用global关键字,明确的引用一个已命名的全局变量

bar=100

def foo():
    print 'calling foo()...'
    global bar
    bar=200
    print 'in foo(), bar is ', bar


print 'bar=',bar
foo()
print 'bar=',bar

运行结果如下:
bar= 100
calling foo()...
in foo(), bar is  200
bar= 200


(7)递归
求阶乘:

>>> def factorial(n):
	if n==0 or n==1:
		return 1
	else:
		return (n*factorial(n-1))

	
>>> factorial(5)
120


(8)生成器,暂时跳过
上一篇:设计模式学习笔记——中介者模式
下一篇:没有了
网友评论