• 网易游戏面试经验(二)


    前言

    在之前我写过一篇博客,讲述了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中闭包所满足的条件为:

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

    装饰器和闭包可以实现一定的封装功能,将函数或者变量封装起来,同时利用他们可以减少代码冗余,减少一些重复工作量。下面举一个例子,如果现在我们想实现一个简单的乘法函数,比如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函数,了解了语言的特性之后,可以极大的提高工作效率,增加代码的美感,提高代码的健壮性。

  • 相关阅读:
    黑洞数
    三态门最简单的描述方法
    数据选择器的符号和真值表
    RGB的同步信号
    奇场和偶场在信号格式上的差别
    CPOL与CPHA
    Pixel Replication
    HDMI传输中MCLK的获得
    Protel99 1:1打印PCB
    二极管和整流管
  • 原文地址:https://www.cnblogs.com/cotyb/p/5338772.html
Copyright © 2020-2023  润新知