用函数来定义函数

在Python中，我们可以在其他函数中定义函数：

defhi(name="yasoob"):print("now you are inside the hi() function")defgreet():return"now you are in the greet() function"defwelcome():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# 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

所以现在我们知道我们可以在其他函数中定义函数了。 换句话说：我们可以做嵌套函数。 现在你需要再学习一点，函数也可以返回函数。

从函数中返回函数

没有必要在另外一个函数中执行函数，我们可以把它作为输出：

defhi(name="yasoob"):defgreet():return"now you are in the greet() function"defwelcome():return"now you are in the welcome() function"ifname=="yasoob":returngreetelse:returnwelcomea=hi()print(a)#outputs: <function greet at 0x7f2143c01500>#This clearly shows that `a` now points to the greet() function in hi()#Now try thisprint(a())#outputs: now you are in the greet() function

@a_new_decoratordefa_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)

fromfunctoolsimportwrapsdefdecorator_name(f):@wraps(f)defdecorated(*args,**kwargs):ifnotcan_run:return"Function will not run"returnf(*args,**kwargs)returndecorated@decorator_namedeffunc():return("Function is running")can_run=Trueprint(func())# Output: Function is runningcan_run=Falseprint(func())# Output: Function will not run

Logging

fromfunctoolsimportwrapsdeflogit(func):@wraps(func)defwith_logging(*args,**kwargs):print(func.__name__+" was called")returnfunc(*args,**kwargs)returnwith_logging@logitdefaddition_func(x):"""Do some math."""returnx+xresult=addition_func(4)# Output: addition_func was called

装饰类

类也可以用来构建装饰器。

classlogit(object):def__init__(self,logfile='out.log'):self.logfile=logfiledef__call__(self,func):log_string=func.__name__+" was called"print(log_string)# Open the logfile and appendwithopen(self.logfile,'a')asopened_file:# Now we log to the specified logfileopened_file.write(log_string+'\n')# Now, send a notificationself.notify()defnotify(self):# logit only logs, no morepass

这个实现有一个额外的好处，就是比嵌套函数方法更简洁，包装一个函数仍然会使用和以前一样的语法：

@logit()
def myfunc1():
pass

现在，让我们继续分类logit添加电子邮件功能（虽然这个主题不会在这里介绍）。

classemail_logit(logit):'''
A logit implementation for sending emails to admins
when the function is called.
'''def__init__(self,email='admin@myproject.com',*args,**kwargs):self.email=emailsuper(email_logit,self).__init__(*args,**kwargs)defnotify(self):# Send an email to self.email# Will not be implemented herepass