网易游戏面试经验(二)

前言

在以前我写过一篇博客,讲述了python的闭包和装饰器,python的装饰器一直是面试热点,也是python很重要的特性之一,不过我认为闭包是装饰器的基础,比装饰器拥有更宽广的概念和做用,因此若是面试官问我关于装饰器的问题,我都会从闭包的角度去分析装饰器,关于这个大块面试官问了我以下几个问题:什么是装饰器?什么是闭包?闭包和装饰器的做用?闭包和装饰器的使用场景?下面从这几个问题出发,在前一篇博客的基础之上更加深入的探讨关于闭包和装饰器的知识html

正文

关于闭包的概念,我从网上找了以下几种说法:python

  • This technique of using the values of outside parameters within a dynamic function is called closures
  • a closure is simply a function with free variables, where the bindings for all such variables are known in advance
  • a closure is a function (object) that remembers its creation environment (enclosing scope)
  • This technique by which some data gets attached to the code is called closure in Python
  • A closure occurs when a function has access to a local variable from an enclosing scope that has finished its execution

上面的话语基本涵盖了闭包的特性,关于这些语句的理解,我仍是先列举一个很是简单的例子:面试

# coding="utf-8"
def fun(msg):
    def nested_fun():
        print msg
    return nested_fun

new_fun = fun("i like python")
new_fun()

上面的代码首先定义了一个函数fun,在这个函数之中再定义了一个嵌套函数,以后返回了这个函数,在这个函数以外,从新将fun函数包括msg参数赋值给了new_fun,以后执行new_fun()函数,运行这段代码,能够发如今console中打印出了i love python这句话。上面的代码有两个注意点:1.函数也是一种对象,能够做为参数返回和传递;2.new_fun=fun("i like python")这句代码实际上是将new_fun指向了fun函数的返回值nested_fun函数,在执行new_fun函数的时候其实在执行了nested_fun函数,在这个函数中打印出的msg对象其实来自于上层函数,并非本身的本地变量,为何还会打印出来呢?因此这就是闭包,根据这个例子能够很好的体会上面列出的几种说法。
在python中闭包所知足的条件为:闭包

  1. 必须拥有嵌套函数
  2. 嵌套函数调用定义在闭包函数里面的值
  3. 闭包函数必须返回嵌套函数

装饰器和闭包能够实现必定的封装功能,将函数或者变量封装起来,同时利用他们能够减小代码冗余,减小一些重复工做量。下面举一个例子,若是如今咱们想实现一个简单的乘法函数,好比times2(n)函数就是给n*2,times5(n)实现给n乘以5,这个功能可使用默认值很容易的实现,代码以下:app

def times2(n, x=2):
    return n * x

print times2(3)

可是这有个明显的缺点,每一个times()函数都须要进行定义细节,如今能够用闭包来实现,代码以下:ide

def multiplier(n):
    def multi(x):
        return x * n
    return multi

times2 = multiplier(2)
times5 = multiplier(5)

print times2(4)
print times5(4)

这段代码的美妙你们能够好好体会一下。
说完了闭包,再说一说装饰器,装饰器就是用函数或者类去封装(装饰)另外一个对象,装饰器支持和被封装的对象相同的接口,因此被装饰的对象甚至感受不到本身被装饰了,在python中,装饰器更多的是一个函数将另外一个函数做为参数,他会利用闭包来实现整个装饰功能,和上面举得闭包的例子不一样的是,装饰器利用的是闭包能够捕获函数。
装饰器的经常使用场景以下:函数

  • 注入参数
  • 记录函数行为
  • 预处理/后处理
  • 修改调用时的上下文

下面简单的列举一个记录函数行为的装饰器的使用:es5

def logging(func):
    def wrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        print func.__name__, args, kwargs
        return res
    return wrapper

@logging
def fib(n):
    if n == 1 or n == 0:
        return 1
    return fib(n-1) + fib(n-2)

print fib(10)

上面的装饰器代码实现了打印被装饰的函数的执行状况,你们能够本身运行。code

总结

语言的美会获得承认和传播,好比lamdba函数,了解了语言的特性以后,能够极大的提升工做效率,增长代码的美感,提升代码的健壮性。htm

相关文章
相关标签/搜索