python︱函数、for、if、_name_、迭代器、防范报错、类定义、装饰器
2017-01-09 18:59
453 查看
新手入门python,开始写一些简单函数,慢慢来,加油~
跟R一样都可以用return返回
lambda函数
lambda表达式有什么好处?匿名函数,一般用来给filter,map这样的函数式编程服务,map(lambda x: x*2,[1,2,3,4,5])
或者就是一次性产品。类似于这种即用即扔的产品:(lambda x: x*2)(3)
或者作为回调函数,传递给某些应用,比如消息处理。
这个输出1,但没有什么意义,仅仅是一个例子。
而在python中的格式为
还是上面的例子
输出的结果是conf中大于2的元素,这里非常有意思的是,将if 和for 循环放在一个[]中就做掉了。
上面是返回conf中大于2的元素,下面是conf中大于2的序号。
conf中大于2的序号。
filter(bool_func,seq):此函数的功能相当于过滤器。调用一个布尔函数bool_func来迭代遍历每个seq中的元素;返回一个使bool_seq返回值为true的元素的序列。
例如:
filter内建函数的python实现:
map(func,seq1[,seq2…]):将函数func作用于给定序列的每个元素,并用一个列表来提供返回值;如果func为None,func表现为身份函数,返回一个含有每个序列中元素集合的n个元组的列表。
例如:
map内建函数的python实现:
reduce(func,seq[,init]):func为二元函数,将func作用于seq序列的元素,每次携带一对(先前的结果以及下一个序列的元素),连续的将现有的结果和下一个值作用在获得的随后的结果上,最后减少我们的序列为一个单一的返回值:如果初始值init给定,第一个比较会是init和第一个序列元素而不是序列的头两个元素。
例如:
reduce的python实现:
python中的for比R中的要广泛很多,R中的for (i in 1:3)循环的较多的是数值,python包括数值+文本列表。
1、字母当做循环
2、列表当做循环
3、数字当做循环
4、for 中的 _ 下划线的应用
for 中出现了 _ 那么作用跟R里面的repeat一致,有复制的功能。
比较小白,对python里面的生成器一开始看不懂,不过后来觉得跟R里面的lappy功能很像。
for iter,_ in l 提取了l=[(“f1”,’g1’),(“f2”,”g2”)]两个的第一个数字,屏蔽了第二个g1/g2
然后f1 f2赋值给了前面的函数,函数内容是iter:np.zeros(2),那么就是出现out[17]的结果。
for _ in h,完全就是repeat两次。
5、while - 重复执行
无限循环的时候,可以用ctrl + C结束。
while 语句用于循环执行程序,即在某条件下,循环执行某段程序,以处理需要重复处理的相同任务。其基本形式为:
(1)常规用法:重复执行
for里面的重复执行,可以用 for _ in np.arrange(10):
(2)continue,break + while
while 语句时还有另外两个重要的命令 continue,break 来跳过循环,continue 用于跳过该次循环,break 则是用于退出循环,此外”判断条件”还可以是个常值,表示循环必定成立,具体用法如下:
(3)循环使用 else 语句
带索引的列表迭代
已知一个列表,刷选出偶数列表方法:
字典推导
和collections库一样,还有一个库叫itertools
_name_在当前文件中:_name_=_main_
_name_在别的文件中:_name_=def的名字
_name_是指示当前py文件调用方式的方法。如果它等于”_main_“就表示是直接执行,如果不是,则用来被别的文件调用,这个时候if就为False,那么它就不会执行最外层的代码了。
比如你有个Python文件里面
这样的话,就算是别的地方导入这个文件,要调用这个XXXX函数,也会执行print “asdf”,因为他是最外层代码,或者叫做全局代码。但是往往我们希望只有我在执行这个文件的时候才运行一些代码,不是的话(也就是被调用的话)那就不执行这些代码,所以一般改为
别的python文档, 调用的话,if name == ‘main‘:以下内容不管了。
同时main()的意义是:python 如何判断应该哪个是主执行文件呢?应用场景是在互相调用python内函数的时候。
来源:Python 初探
.
.
类似R中的stopifnot
参考博客:Python 中何时使用断言?
.
如果try中open不出来,那么就except返回相应的内容“fail to open”
参考
看一个案例:
1、str(e)
返回字符串类型,只给出异常信息,不包括异常信息的类型,如1/0的异常信息
‘integer division or modulo by zero’
2、repr(e)
给出较全的异常信息,包括异常信息的类型,如1/0的异常信息
“ZeroDivisionError(‘integer division or modulo by zero’,)”
3、e.message
获得的信息同str(e)
4、采用traceback模块
需要导入traceback模块,此时获取的信息最全,与python命令行运行程序出现错误信息一致。使用traceback.print_exc()打印异常信息到标准错误,就像没有获取一样,或者使用traceback.format_exc()将同样的输出获取为字符串。你可以向这些函数传递各种各样的参数来限制输出,或者重新打印到像文件类型的对象。
或者:
.
来源:Python模块学习:logging 日志记录
就会在指定目录里面,载入到Log.txt之中
来看看在Log中显示如下:
所以,在 log.exception()可以简单定义一些关键词来帮助定位问题所在。
.
当python执行这一句时,会调用enter函数,然后把该函数return的值传给as后指定的变量。
之后,python会执行下面do something的语句块。最后不论在该语句块出现了什么异常,都会在离开时执行exit。
那么try和with也可以合起:
延伸:报错提示如何写ValueError()
.
.
类需注意:
类适合存函数,不用非要return
在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。
这样save_def里面就会一直存着name、score函数。
初始化的方式跟函数一样,直接传入。
同时,initialization.name,initialization.score 也相当于initialization的属性。
不过,如果你觉得还需要额外加入一些临时属性的话,可以直接赋值:
.
如果类里面包着函数,而且函数里面包着属性,那么可以直接用:
如果是函数的话,则为:
不同的地方在于类里面,可以直接用类内存着的函数。
.
self.function1就是一种类内调用函数的方式。从这一案例可以看出:
类内调用函数+参数,都需要用self.
.
笔者在调用另一个.py文件中的类的时候,发生大面积的报错:
无奈只能写在一个文档中。
一般来说,调用的方式有两种:import 和 from…import…:
通俗的说:
.
其中笔者认为,类class适合打包函数,装饰器@适合包装函数,并不是包装参数。 同时,装饰器适合,函数之间有一定递进、级联关系,比较适合。
这里面调用func的时候就产生了一个闭包——inner_func,并且该闭包持有自由变量——name,因此这也意味着,当函数func的生命周期结束之后,name这个变量依然存在,因为它被闭包引用了,所以不会被回收。
.
上例就是纯手工实现的一个最简单的装饰器。装饰器函数outer并没有修改被装饰函数wait_for_deco,但我们调用被装饰后的decorated函数闭包却能够得到原函数的加强版结果,还能进行额外的操作。
超级简单的案例一则:
.
.
可调节的多参数
按照上面这种写法虽然可以传参了但有个缺陷,参数个数不确定的函数就没法使用这个装饰器了。
超级简单案例一则:
.
.
结果:
一、函数 +三个内建函数filter,map和reduce + if
1、def/lambda
def myadd(a=1,b=100): result = 0 i = a while i <= b: # 默认值为1+2+3+……+100 result += i i += 1 return result
跟R一样都可以用return返回
lambda函数
lambda表达式有什么好处?匿名函数,一般用来给filter,map这样的函数式编程服务,map(lambda x: x*2,[1,2,3,4,5])
或者就是一次性产品。类似于这种即用即扔的产品:(lambda x: x*2)(3)
或者作为回调函数,传递给某些应用,比如消息处理。
2、if
python 中的三元表达式(三目运算符)这个输出1,但没有什么意义,仅仅是一个例子。
而在python中的格式为
为真时的结果 if 判定条件 else 为假时的结果
还是上面的例子
1 if 5>3 else 0
如果if + for列表的方式同时使用:
conf = (11,2,3) [i for i in conf if i > 2] >>> [11, 3]
输出的结果是conf中大于2的元素,这里非常有意思的是,将if 和for 循环放在一个[]中就做掉了。
上面是返回conf中大于2的元素,下面是conf中大于2的序号。
conf = (11,2,3) [i for i, c in enumerate(conf) if c > 2] >>> [0, 2]
conf中大于2的序号。
3、filter
来源:Python内建函数之——filter,map,reducefilter(bool_func,seq):此函数的功能相当于过滤器。调用一个布尔函数bool_func来迭代遍历每个seq中的元素;返回一个使bool_seq返回值为true的元素的序列。
例如:
>>> filter(lambda x : x%2 == 0,[1,2,3,4,5]) [2, 4]
filter内建函数的python实现:
def filter(bool_func,seq): filtered_seq = [] for eachItem in seq: if bool_func(eachItem): filtered_seq.append(eachItem) return filtered_seq
4、map
来源:Python内建函数之——filter,map,reducemap(func,seq1[,seq2…]):将函数func作用于给定序列的每个元素,并用一个列表来提供返回值;如果func为None,func表现为身份函数,返回一个含有每个序列中元素集合的n个元组的列表。
例如:
>>> map(lambda x : None,[1,2,3,4]) [None, None, None, None] >>> map(lambda x : x * 2,[1,2,3,4]) [2, 4, 6, 8] >>> map(lambda x : x * 2,[1,2,3,4,[5,6,7]]) [2, 4, 6, 8, [5, 6, 7, 5, 6, 7]] >>> map(lambda x : None,[1,2,3,4]) [None, None, None, None]
map内建函数的python实现:
>>> def map(func,seq): mapped_seq = [] for eachItem in seq: mapped_seq.append(func(eachItem)) return mapped_seq
5、reduce
来源:Python内建函数之——filter,map,reducereduce(func,seq[,init]):func为二元函数,将func作用于seq序列的元素,每次携带一对(先前的结果以及下一个序列的元素),连续的将现有的结果和下一个值作用在获得的随后的结果上,最后减少我们的序列为一个单一的返回值:如果初始值init给定,第一个比较会是init和第一个序列元素而不是序列的头两个元素。
例如:
>>> reduce(lambda x,y : x + y,[1,2,3,4]) 10 >>> reduce(lambda x,y : x + y,[1,2,3,4],10) 20
reduce的python实现:
def reduce(bin_func,seq,initial=None): lseq = list(seq) if initial is None: res = lseq.pop(0) else: res = initial for eachItem in lseq: res = bin_func(res,eachItem) return res
二、for、while
博客:Python for 循环语句python中的for比R中的要广泛很多,R中的for (i in 1:3)循环的较多的是数值,python包括数值+文本列表。
1、字母当做循环
for letter in 'Python': # 第一个实例 print '当前字母 :', letter 当前字母 : P 当前字母 : y 当前字母 : t 当前字母 : h 当前字母 : o 当前字母 : n
2、列表当做循环
fruits = ['banana', 'apple', 'mango'] for fruit in fruits: # 第二个实例 print '当前字母 :', fruit
3、数字当做循环
for num in range(10,20): # 迭代 10 到 20 之间的数字 for i in range(2,num): # 根据因子迭代 if num%i == 0: # 确定第一个因子 j=num/i # 计算第二个因子 print '%d 等于 %d * %d' % (num,i,j) break # 跳出当前循环 else: # 循环的 else 部分 print num, '是一个质数'
4、for 中的 _ 下划线的应用
for 中出现了 _ 那么作用跟R里面的repeat一致,有复制的功能。
import numpy as np l=[("f1",'g1'),("f2","g2")] h=['go1','go2'] In [17]:{iter:np.zeros(2) for iter,_ in l } Out[17]: {'f1': array([ 0., 0.]), 'f2': array([ 0., 0.])} In [18]:[{iter:np.zeros(2) for iter,_ in l } for _ in h] Out[18]: [{'f1': array([ 0., 0.]), 'f2': array([ 0., 0.])}, {'f1': array([ 0., 0.]), 'f2': array([ 0., 0.])}]
比较小白,对python里面的生成器一开始看不懂,不过后来觉得跟R里面的lappy功能很像。
for iter,_ in l 提取了l=[(“f1”,’g1’),(“f2”,”g2”)]两个的第一个数字,屏蔽了第二个g1/g2
然后f1 f2赋值给了前面的函数,函数内容是iter:np.zeros(2),那么就是出现out[17]的结果。
for _ in h,完全就是repeat两次。
5、while - 重复执行
无限循环的时候,可以用ctrl + C结束。
while 语句用于循环执行程序,即在某条件下,循环执行某段程序,以处理需要重复处理的相同任务。其基本形式为:
(1)常规用法:重复执行
#!/usr/bin/python count = 0 while (count < 9): print 'The count is:', count count = count + 1 print "Good bye!" The count is: 0 The count is: 1 The count is: 2 The count is: 3 The count is: 4 The count is: 5 The count is: 6 The count is: 7 The count is: 8 Good bye!
for里面的重复执行,可以用 for _ in np.arrange(10):
(2)continue,break + while
while 语句时还有另外两个重要的命令 continue,break 来跳过循环,continue 用于跳过该次循环,break 则是用于退出循环,此外”判断条件”还可以是个常值,表示循环必定成立,具体用法如下:
# continue 和 break 用法i = 1 while i < 10: i += 1 if i%2 > 0: # 非双数时跳过输出 continue print i # 输出双数2、4、6、8、10i = 1 while 1: # 循环条件为1必定成立 print i i += 1 if i > 10: # 当i大于10时跳出循环 break
(3)循环使用 else 语句
#!/usr/bin/python count = 0 while count < 5: print count, " is less than 5" count = count + 1 else: print count, " is not less than 5" >>> 0 is less than 5 1 is less than 5 2 is less than 5 3 is less than 5 4 is less than 5 5 is not less than 5
三、迭代器
两个列表同时迭代nfc = ["Packers", "49ers"] afc = ["Ravens", "Patriots"] for teama, teamb in zip(nfc, afc): print teama + " vs. " + teamb >>> Packers vs. Ravens >>> 49ers vs. Patriots
带索引的列表迭代
teams = ["Packers", "49ers", "Ravens", "Patriots"] for index, team in enumerate(teams): print index, team >>> 0 Packers >>> 1 49ers >>> 2 Ravens >>> 3 Patriots
已知一个列表,刷选出偶数列表方法:
numbers = [1,2,3,4,5,6] even = [] for number in numbers: if number%2 == 0: even.append(number)
字典推导
teams = ["Packers", "49ers", "Ravens", "Patriots"] print {key: value for value, key in enumerate(teams)} >>> {'49ers': 1, 'Ravens': 2, 'Patriots': 3, 'Packers': 0}
和collections库一样,还有一个库叫itertools
from itertools import combinations teams = ["Packers", "49ers", "Ravens", "Patriots"] for game in combinations(teams, 2): print game >>> ('Packers', '49ers') >>> ('Packers', 'Ravens') >>> ('Packers', 'Patriots') >>> ('49ers', 'Ravens') >>> ('49ers', 'Patriots') >>> ('Ravens', 'Patriots')
四、_name_
参考来自:百度知道_name_在当前文件中:_name_=_main_
_name_在别的文件中:_name_=def的名字
_name_是指示当前py文件调用方式的方法。如果它等于”_main_“就表示是直接执行,如果不是,则用来被别的文件调用,这个时候if就为False,那么它就不会执行最外层的代码了。
比如你有个Python文件里面
def XXXX(): #body print "asdf"
这样的话,就算是别的地方导入这个文件,要调用这个XXXX函数,也会执行print “asdf”,因为他是最外层代码,或者叫做全局代码。但是往往我们希望只有我在执行这个文件的时候才运行一些代码,不是的话(也就是被调用的话)那就不执行这些代码,所以一般改为
def XXXX(): #body if __name__="__main__": print "asdf"
延伸:if _name_ == ‘_main_‘:
本python文档,if name == ‘main‘:以下的内容可以执行,别的python文档, 调用的话,if name == ‘main‘:以下内容不管了。
同时main()的意义是:python 如何判断应该哪个是主执行文件呢?应用场景是在互相调用python内函数的时候。
来源:Python 初探
.
.
五、防范报错
1、assert 断言
Python的assert是用来检查一个条件,如果它为真,就不做任何事。如果它为假,则会抛出AssertError并且包含错误信息。例如:py> x = 23 py> assert x > 0, "x is not zero or negative" py> assert x%2 == 0, "x is not an even number" Traceback (most recent call last): File "", line 1, in AssertionError: x is not an even number
类似R中的stopifnot
参考博客:Python 中何时使用断言?
.
2、try…except…
try: f = open('xxx') except: print 'fail to open' exit(-1)
如果try中open不出来,那么就except返回相应的内容“fail to open”
try: <语句> #运行别的代码 except <名字>: <语句> #如果在try部份引发了'name'异常 except <名字>,<数据>: <语句> #如果引发了'name'异常,获得附加的数据 else: <语句> #如果没有异常发生
参考
看一个案例:
try: print('I am sure no exception is going to occur!') except Exception: print('exception') else: # 这里的代码只会在try语句里没有触发异常时运行, # 但是这里的异常将 *不会* 被捕获 print('This would only run if no exception occurs. And an error here ' 'would NOT be caught.') finally: print('This would be printed in every case.') # Output: I am sure no exception is going to occur! # This would only run if no exception occurs. # This would be printed in every case.
报错并提示异常信息:
来源:Python中获取异常(Exception)信息1、str(e)
返回字符串类型,只给出异常信息,不包括异常信息的类型,如1/0的异常信息
‘integer division or modulo by zero’
2、repr(e)
给出较全的异常信息,包括异常信息的类型,如1/0的异常信息
“ZeroDivisionError(‘integer division or modulo by zero’,)”
3、e.message
获得的信息同str(e)
4、采用traceback模块
需要导入traceback模块,此时获取的信息最全,与python命令行运行程序出现错误信息一致。使用traceback.print_exc()打印异常信息到标准错误,就像没有获取一样,或者使用traceback.format_exc()将同样的输出获取为字符串。你可以向这些函数传递各种各样的参数来限制输出,或者重新打印到像文件类型的对象。
try: 1/0 except Exception, e: print 'str(Exception):\t', str(Exception) print 'str(e):\t\t', str(e) print 'repr(e):\t', repr(e) print 'e.message:\t', e.message print 'traceback.print_exc():'; traceback.print_exc() print 'traceback.format_exc():\n%s' % traceback.format_exc()
或者:
def this_fails(): x = 1/0 try: this_fails() except : print('Handling run-time error:') raise print(1)
.
3、报错日志记录:Logger.exception
以ERROR级别记录日志消息,异常跟踪信息将被自动添加到日志消息里。Logger.exception通过用在异常处理块中,如:来源:Python模块学习:logging 日志记录
import logging logging.basicConfig(filename = os.path.join(os.getcwd(), 'log.txt'), level = logging.DEBUG) log = logging.getLogger('root') try: a===b except: log.exception('exception') #异常信息被自动添加到日志消息中
就会在指定目录里面,载入到Log.txt之中
来看看在Log中显示如下:
ERROR:root:exception Traceback (most recent call last): File "test.py", line 12, in <module> a==b NameError: name 'a' is not defined
所以,在 log.exception()可以简单定义一些关键词来帮助定位问题所在。
.
4、with…as…
那么with和as也是一种防止报错的防范方式,当python执行这一句时,会调用enter函数,然后把该函数return的值传给as后指定的变量。
之后,python会执行下面do something的语句块。最后不论在该语句块出现了什么异常,都会在离开时执行exit。
ith open("x.txt") as f: data = f.read() with open("x.txt") as f1, open('xxx.txt') as f2: do something with f1,f2
那么try和with也可以合起:
try: with open( "a.txt" ) as f : do something except xxxError: do something about exception
延伸:报错提示如何写ValueError()
if pretrained_model not in self._models: raise ValueError( 'The n_class needs to be supplied as an argument.')
.
.
六、类定义
参考于:Python的hasattr() getattr() setattr() 函数使用方法详解class <类名>: <语句>
类需注意:
类适合存函数,不用非要return
在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。
1、类里面一直存着参数
init存入class save_def(object): def __init__(self, name, score): self.name = name self.score = score
这样save_def里面就会一直存着name、score函数。
initialization = save_def(name,score)
初始化的方式跟函数一样,直接传入。
同时,initialization.name,initialization.score 也相当于initialization的属性。
不过,如果你觉得还需要额外加入一些临时属性的话,可以直接赋值:
initialization.other = "other"
.
2、类里面函数如何调用
类内的参数前面加self.paraclass save_def(object): def __init__(self, name, score): self.name = name self.score = score def function1(self,dataframe): temp_data = type(dataframe[self.name]) return temp_data
如果类里面包着函数,而且函数里面包着属性,那么可以直接用:
initialization = save_def(name,score) initialization.function1(dataframe)
如果是函数的话,则为:
>>>def function1(name,dataframe): temp_data = type(dataframe[name]) return temp_data >>>function1(name,dataframe)
不同的地方在于类里面,可以直接用类内存着的函数。
.
3、类内函数套函数
类内函数调用类内的函数,前面需要加self.class save_def(object): def __init__(self, name, score): self.name = name self.score = score def function1(self,dataframe): temp_data = type(dataframe[self.name]) return temp_data def function2(self): temp_data2 = self.function1(dataframe.ix[self.score>10,:])
self.function1就是一种类内调用函数的方式。从这一案例可以看出:
类内调用函数+参数,都需要用self.
.
延伸一:关于如何从调用另一个.py文件中的类
因为,Python里面全局变量所谓的全局是针对在一个文件里面的函数而言的,跨文件就等于定义在不同的包里面,也就相当于是使用了不同的命名空间。(来源:PYTHON全局变量在模块中的无法引用?)笔者在调用另一个.py文件中的类的时候,发生大面积的报错:
globel name 'xxx' is not defined
无奈只能写在一个文档中。
一般来说,调用的方式有两种:import 和 from…import…:
import datetime print(datetime.datetime.now()) from datetime import datetime print(datetime.now())
通俗的说:
from import : 从车里把矿泉水拿出来,给我 import : 把车给我
.
七、装饰器
参考于:深入浅出Python装饰器、Python装饰器学习(九步入门)、Python 的闭包和装饰器其中笔者认为,类class适合打包函数,装饰器@适合包装函数,并不是包装参数。 同时,装饰器适合,函数之间有一定递进、级联关系,比较适合。
1、闭包
装饰器相当于升级版的闭包,一个闭包就是你调用了一个函数A,这个函数A返回了一个函数B给你。这个返回的函数B就叫做闭包。你在调用函数A的时候传递的参数就是自由变量。def func(name): def inner_func(age): print 'name:', name, 'age:', age return inner_func bb = func('the5fire') bb(26) # >>> name: the5fire age: 26
这里面调用func的时候就产生了一个闭包——inner_func,并且该闭包持有自由变量——name,因此这也意味着,当函数func的生命周期结束之后,name这个变量依然存在,因为它被闭包引用了,所以不会被回收。
.
2、初级装饰器
函数传入、函数传出,装饰器的本质就是函数闭包,或者说利用了函数闭包的特性。def outer(function): def inner(): print("执行function之前可以进行额外操作") result = function() print("执行function之后还可以进行额外操作") result *= 2 # 对function的返回值本身进行额外操作 return result # 返回‘加强’后的结果 return inner def wait_for_deco(): return 1024 decorated = outer(wait_for_deco) print decorated() # 输出 2048
上例就是纯手工实现的一个最简单的装饰器。装饰器函数outer并没有修改被装饰函数wait_for_deco,但我们调用被装饰后的decorated函数闭包却能够得到原函数的加强版结果,还能进行额外的操作。
超级简单的案例一则:
def function1(function): return function() + 1 # function作为参数传入,且这个参数名称是任意的,跟普通参数一致,需要对齐,函数也要写function def function2(): return 2 #这样的装饰器,一般不传入参数 # 使用 >>> function1(function2) >>> 3 # 其中,不能写成function1(function2())
.
3、带装饰符@-装饰器
实际上装饰符@就仅仅是帮我们自动地把返回的闭包函数名字替换为原函数的名字。def outer(function): def inner(): print("执行function之前可以进行额外操作") result = function() print("执行function之后还可以进行额外操作") result *= 2 # 对function的返回值本身进行额外操作 return result # 返回‘加强’后的结果 return inner @outer def wait_for_deco(): return 1024 print wait_for_deco() # 输出 2048
.
4、带参数+装饰符的装饰器
# 例如为下面的函数写一个装饰器,应该在内部的wapper中按原样传递参数 def decorator(func): def wrapper(x, y) ret = func(x, y) # 原函数的返回值 return ret*2 # 原函数的结果“加强”后再返回 return wrapper @decorator def wait_for_deco(x, y): return x + y print(wait_for_deco(1, 2)) # 输出 6
可调节的多参数
按照上面这种写法虽然可以传参了但有个缺陷,参数个数不确定的函数就没法使用这个装饰器了。
def decorator(func): def wrapper(*args, **kwargs) ret = func(*args, **kwargs) return ret*2 return wrapper @decorator def wait_for_deco_a(x, y): return x + y @decorator def wait_for_deco_b(x, y, z): return x + y + z print(wait_for_deco_a(1, 2)) 6 print(wait_for_deco_b(1, 2, 3)) 12
超级简单案例一则:
def function2(function): # 因为要传入参数,所以下面的def 就相当于在写了一次_function2,但也不是简单的加个def,其中_代表,专属于函数内 def _function2(b): # 并不能写出:function2(function) a = function(b) return a + 1 return _function2 # 返回的是函数本身 @function2 def function1(b): return b + 1 function2(function1)
.
5、传参数+装饰符@+多选项装饰器
来源文章:Python装饰器02def mydec(is_print): def mydec_f(func): def mydec_a(*args, **kwargs): r = func(*args, **kwargs) if is_print: print("结果是:{}".format(r)) else: print("不打印结果") return mydec_a return mydec_f @mydec(True) def mysum(a, b): c = a + b return c @mydec(False) def mysum2(a, b, c): d = a + b + c return d mysum(1, 2) mysum2(1, 2, 3) >>>结果是:3
.
6、传参数+装饰符@+类 装饰器
来源文章:Python装饰器02class mycls(): def __init__(self): print("类初始化了") @staticmethod def test1(): print("我是mycls.test1") @staticmethod def test2(): print("我是mycls.test2") # 装饰器 def mydec(cls): def mydec_f(func): def mydec_a(*args, **kwargs): cls.test1() r = func(*args, **kwargs) print("结果是:{}".format(r)) cls.test2() return mydec_a return mydec_f @mydec(mycls) def mysum(a, b): c = a + b return c @mydec(mycls) def mysum2(a, b, c): d = a + b + c return d mysum(1, 2) mysum2(1, 2, 3)
结果:
我是mycls.test1 结果是:3 我是mycls.test2 我是mycls.test1 结果是:6 我是mycls.test2
相关文章推荐
- Python动态类型的学习---引用的理解
- Python3写爬虫(四)多线程实现数据爬取
- 垃圾邮件过滤器 python简单实现
- 下载并遍历 names.txt 文件,输出长度最长的回文人名。
- install and upgrade scrapy
- Scrapy的架构介绍
- Centos6 编译安装Python
- 使用Python生成Excel格式的图片
- 让Python文件也可以当bat文件运行
- [Python]推算数独
- Python中zip()函数用法举例
- Python中map()函数浅析
- 设计模式之行为型模式 - 调用行为的传递问题
- Python将excel导入到mysql中
- Python在CAM软件Genesis2000中的应用
- 使用Shiboken为C++和Qt库创建Python绑定
- FREEBASIC 编译可被python调用的dll函数示例