預備知識:
*args的使用方法,
*args 用來將參數打包成tuple給函數體調用
例子一:
>>> def function(*args):
print(args, type(args))
>>>
>>> function(1)
(1,) <class 'tuple'>
>>> function(2)
(2,) <class 'tuple'>
例子二:
def function(x, y, *args):
print(x, y, args)
function(1, 2, 3, 4, 5)
output :
**kwargs的使用方法
**kwargs 打包關鍵字參數成dict給函數體調用
def function(**kwargs):
print( kwargs, type(kwargs))
function(a=2)
output :
>>> function(a=2)
{'a': 2} <class 'dict'>
>>>
例子二:
def function(**kwargs):
print(kwargs)
function(a=1, b=2, c=3)
output :
>>> function(a=1, b=2, c=3)
{'b': 2, 'a': 1, 'c': 3}
>>>
注意點:參數arg、*args、**kwargs三個參數的位置必須是一定的。必須是(arg,*args,**kwargs)這個順序,否則程序會報錯。
def function(arg,*args,**kwargs):
print(arg,args,kwargs)
function(6,7,8,9,a=1, b=2, c=3)
output :
>>> function(6,7,8,9,a=1, b=2, c=3)
6 (7, 8, 9) {'b': 2, 'a': 1, 'c': 3}
>>>
Everything in Python is an object:
First of all let’s understand functions in Python:
def hi(name="yasoob"):
return "hi " + name
print(hi())
若print (hi) #不帶括號,會打印什麼:
沒錯,它就是一個函數。
when you put a pair of parentheses after it, the function gets executed; whereas if you don’t put parenthesis after it, then it can be passed around and can be assigned to other variables without executing it. Did you get it?
def hi(name="yasoob"):
return "hi " + name
print(hi())
# We can even assign a function to a variable like
greet = hi
# We are not using parentheses here because we are not calling the function hi
# instead we are just putting it into the greet variable. Let's try to run this
print(greet())
# output: 'hi yasoob'
print(greet)
#output :<function hi at 0x0000023D1411D7B8>
# Let's see what happens if we delete the old hi function!
del hi
print(hi())
#outputs: NameError: name 'hi' is not defined
print(greet())
#outputs: 'hi yasoob'
既然我們可以assign a function to a variable,那不妨試試:
>>> f = greet
>>> g = greet
>>> print (f)
<function hi at 0x0000023D1411D7B8>
>>> print (g)
<function hi at 0x0000023D1411D7B8>
>>>
可見都指向了同一塊內存。
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(welcome())#故意先寫welcome()
print(greet())
print("now you are back in the hi() function")
hi()
#output:now you are inside the hi() function
# now you are in the welcome() function
# now you are in the greet() function
# now you are back in the hi() function
# This shows that whenever you call hi(), greet() and welcome()
# are also called. However the greet() and welcome() functions
# are not available outside the hi() function e.g:
greet()
#outputs: NameError: name 'greet' is not defined 在外面greet()就不可見了。
So now we know that we can define functions in other functions. In other words: we can make nested functions. Now you need to learn one more thing, that functions can return functions too.
It is not necessary to execute a function within another function, we can return it as an output as well:
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>
#This clearly shows that `a` now points to the greet() function in hi()
#Now try this
print(a())
#outputs: now you are in the greet() function
既然函數可以傳遞給其他變量,那也是說可把函數作爲一個參數傳遞給另外一個函數:
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!
好可,真正的裝飾器來了:
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()
其實下面的纔是真正的:
哈哈哈.
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")
print ("*******************************************************")
@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)
參考:
http://book.pythontips.com/en/latest/decorators.html
再看一個例子:
import time
def calc_square(numbers):
start = time.time()
result = []
for number in numbers:
result.append (number*number)
end = time.time()
print ("calc_square took " + str((end-start)*1000) + "mil sec")
return result
def calc_cube(numbers):
start = time.time()
result = []
for number in numbers:
result.append (number*number*number)
end = time.time()
print ("calc_cube took " + str((end-start)*1000) + "mil sec")
return result
array = range(1,100000)
out_square = calc_square(array)
out_cube = calc_cube(array)
看下用了多久:calc_square 10ms
再對比下用裝飾器的效果:
import time
def timer(func):
def wrapper(*args, **kwargs):
#https://www.geeksforgeeks.org/decorators-in-python/
start = time.time()
#result = []
result = func(*args, **kwargs)
end = time.time()
print (func.__name__ +"took" + str((end-start)*1000) + "mil sec")
return result
return wrapper
@timer
def calc_square(numbers):
result = []
for number in numbers:
result.append (number*number)
return result
@timer
def calc_cube(numbers):
result = []
for number in numbers:
result.append (number*number*number)
return result
#x= calc_square([1,2,3,4,5])
#print (x)
array = range(1,100000)
out_square = calc_square(array)
out_cube = calc_cube(array)
變長了一點點。