您的位置:首页 > 职场人生

网易游戏面试经验(二)

2016-03-30 20:36 525 查看

前言

在之前我写过一篇博客,讲述了python的闭包和装饰器,python的装饰器一直是面试热点,也是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中闭包所满足的条件为:

必须拥有嵌套函数

嵌套函数调用定义在闭包函数里面的值

闭包函数必须返回嵌套函数

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

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

print times2(3)

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

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

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

print times2(4)
print times5(4)

这段代码的美妙大家可以好好体会一下。

说完了闭包,再说一说装饰器,装饰器就是用函数或者类去封装(装饰)另一个对象,装饰器支持和被封装的对象相同的接口,所以被装饰的对象甚至感觉不到自己被装饰了,在python中,装饰器更多的是一个函数将另一个函数作为参数,他会利用闭包来实现整个装饰功能,和上面举得闭包的例子不同的是,装饰器利用的是闭包可以捕获函数。

装饰器的常用场景如下:

注入参数

记录函数行为

预处理/后处理

修改调用时的上下文

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

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)

上面的装饰器代码实现了打印被装饰的函数的执行情况,大家可以自己运行。

总结

语言的美会得到认可和传播,比如lamdba函数,了解了语言的特性之后,可以极大的提高工作效率,增加代码的美感,提高代码的健壮性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: