1.引子:函数也是对象
木有括号的函数那就不是在调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
def hi(name = "yasoob" ): return "hi " + name print (hi()) # output: 'hi yasoob' # 我们甚至可以将一个函数赋值给一个变量,比如 greet = hi # 我们这里没有在使用小括号,因为我们并不是在调用hi函数 # 而是在将它放在greet变量里头。我们尝试运行下这个 print (greet()) # output: 'hi yasoob' # 如果我们删掉旧的hi函数,看看会发生什么! del hi print (hi()) #outputs: NameError print (greet()) #outputs: 'hi yasoob' |
2.函数内的函数
(1)在python中,一个函数内能嵌套定义另一个函数,并且可以在该大函数内调用该小函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
def hi(name = "yasoob" ): print ( "now you are inside the hi() function" ) def greet(): return "now you are in the greet() function" def welcome(): return "now you are in the welcome() function" print (greet()) print (welcome()) print ( "now you are back in the hi() function" ) hi() #output:now you are inside the hi() function # now you are in the greet() function # now you are in the welcome() function # now you are back in the hi() function # 上面展示了无论何时你调用hi(), greet()和welcome()将会同时被调用。 # 然后greet()和welcome()函数在hi()函数之外是不能访问的,比如: greet() #outputs: NameError: name 'greet' is not defined |
(2)开始神奇的是,大函数的返回值可以是一个函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
def hi(name = "yasoob" ): def greet(): return "now you are in the greet() function" def welcome(): return "now you are in the welcome() function" if name = = "yasoob" : return greet #这里!! else : return welcome a = hi() print (a) #outputs: <function greet at 0x7f2143c01500> #上面清晰地展示了`a`现在指向到hi()函数中的greet()函数 #现在试试这个 print (a()) #outputs: now you are in the greet() function |
在 if/else 语句中我们返回 greet 和 welcome,而不是 greet() 和 welcome()。
为什么那样?这是因为当你把一对小括号放在后面,这个函数就会执行;然而如果你不放括号在它后面,那它可以被到处传递,并且可以赋值给别的变量而不去执行它。
当我们写下 a = hi(),hi() 会被执行,而由于 name 参数默认是 yasoob,所以函数 greet 被返回了。
PS:如果我们打印出 hi()(),这会输出 now you are in the greet() function。
(3)最后要说的是函数作为参数传入一个函数:
1
2
3
4
5
6
7
8
|
def hi(): return "hi yasoob!" def doSomethingBeforeHi(func): print ( "I am doing some boring work before executing hi()" ) print (func()) doSomethingBeforeHi(hi) #outputs:I am doing some boring work before executing hi() # hi yasoob! |
3.装饰器小栗子
终于来到了带@的装饰器,其实就是带了@帽子的函数作为参数,传入@后面的函数中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
def a_new_decorator(a_func): def wrapTheFunction(): print ( "I am doing some boring work before executing a_func()" ) a_func() print ( "I am doing some boring work after executing a_func()" ) return wrapTheFunction @a_new_decorator def a_function_requiring_decoration(): """Hey you! Decorate me!""" print ( "I am the function which needs some decoration to " "remove my foul smell" ) a_function_requiring_decoration() #outputs: I am doing some boring work before executing a_func() # I am the function which needs some decoration to remove my foul smell # I am doing some boring work after executing a_func() #the @a_new_decorator is just a short way of saying: a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration) |
上面的代码等价于我们熟悉的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
def a_new_decorator(a_func): def wrapTheFunction(): print ( "I am doing some boring work before executing a_func()" ) a_func() print ( "I am doing some boring work after executing a_func()" ) return wrapTheFunction def a_function_requiring_decoration(): print ( "I am the function which needs some decoration to remove my foul smell" ) a_function_requiring_decoration() #outputs: "I am the function which needs some decoration to remove my foul smell" a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration) #now a_function_requiring_decoration is wrapped by wrapTheFunction() a_function_requiring_decoration() #outputs:I am doing some boring work before executing a_func() # I am the function which needs some decoration to remove my foul smell # I am doing some boring work after executing a_func() |
不过一开始上面被装饰过的函数名字已经悄悄发生“改变”,如果print下可以看出(如下代码)。
解决方案:
@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。
1
2
|
print (a_function_requiring_decoration.__name__) # Output: wrapTheFunction |
最终加上@wraps的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
from functools import wraps def a_new_decorator(a_func): @wraps (a_func) def wrapTheFunction(): print ( "I am doing some boring work before executing a_func()" ) a_func() print ( "I am doing some boring work after executing a_func()" ) return wrapTheFunction @a_new_decorator def a_function_requiring_decoration(): """Hey yo! Decorate me!""" print ( "I am the function which needs some decoration to " "remove my foul smell" ) print (a_function_requiring_decoration.__name__) # Output: a_function_requiring_decoration |
5.property和setter用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class Timer: def __init__( self , value = 0.0 ): self ._time = value self ._unit = 's' # 使用装饰器的时候,需要注意: # 1. 装饰器名,函数名需要一直 # 2. property需要先声明,再写setter,顺序不能倒过来 @property def time( self ): return str ( self ._time) + ' ' + self ._unit @time .setter def time( self , value): if (value < 0 ): raise ValueError( 'Time cannot be negetive.' ) self ._time = value t = Timer() t.time = 1.0 print (t.time) |
到此这篇关于python装饰器property和setter用法的文章就介绍到这了,更多相关python property与setter内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://blog.51cto.com/u_15717393/5470902