首页 存档 技术 查看内容

听说你会Python?做几道题呗

2018-3-30 13:00 |来自: 互联网 341 0

摘要: 作者:manjusaka 原文链接:http://manjusaka.itscoder.com/2016/11/18/Someone-tell-me-that-you-think-Python-is-**/ 前言 最近觉得 Python 太"简单了",于是在**川爷面前放肆了一把:"我觉得 Python ...

作者:manjusaka

原文链接:http://manjusaka.itscoder.com/2016/11/18/Someone-tell-me-that-you-think-Python-is-simple/

前言

最近觉得 Python 太"简单了",于是在师父川爷面前放肆了一把:"我觉得 Python 是世界上最简单的语言!"。于是川爷嘴角闪过了一丝轻蔑的微笑(内心 OS:Naive,作为一个 Python 开发者,我必须要给你一点人生经验,不然你不知道天高地厚!)于是川爷给我了一份满分 100 分的题,然后这篇文章就是记录下做这套题所踩过的坑。

1.列表生成器

描述

下面的代码会报错,为什么?

  1. class A(object):

  2. x = 1

  3. gen = (x for _ in xrange(10)) # gen=(x for _ in range(10))

  4. if __name__ == "__main__":

  5. print(list(A.gen))

答案

这个问题是变量作用域问题,在gen=(xfor_inxrange(10))gen是一个generator,在generator中变量有自己的一套作用域,与其余作用域空间相互隔离。因此,将会出现这样的NameError:name' x 'isnotdefined的问题,那么解决方案是什么呢?答案是:用 lambda 。

  1. class A(object):

  2. x = 1

  3. gen = (lambda x: (x for _ in xrange(10)))(

  4. x) # gen=(x for _ in range(10))

  5. if __name__ == "__main__":

  6. print(list(A.gen))

或者这样

  1. class A(object):

  2. x = 1

  3. gen = (A.x for _ in xrange(10)) # gen=(x for _ in range(10))

  4. if __name__ == "__main__":

  5. print(list(A.gen))

补充

感谢评论区几位提出的意见,这里我给一份官方文档的说明吧:

The scope of names defined in a class block is limited to the class block ; it does not extend to the code blocks of methods - this includes comprehensions and generator expressions since they are implemented using a function scope. This means that the following will fail :

  1. class A:

  2. a = 42

  3. b = list(a i for i in range(10))

参考链接Python 2 Execution-Model:Naming-and-BindingPython 3 Execution-Model:Resolution-of-Names。据说这是 PEP 227 中新增的提案,我回去会进一步详细考证。再次拜谢评论区 @没头脑很着急 @涂伟忠 @ Cholerae 三位的勘误指正。

2.装饰器

描述

我想写一个类装饰器用来度量函数/方法运行时间

  1. import time

  2. class Timeit(object):

  3. def __init__(self, func):

  4. self._wrapped = func

  5. def __call__(self, *args, **kws):

  6. start_time = time.time()

  7. result = self._wrapped(*args, **kws)

  8. print("elapsed time is %s " % (time.time() - start_time))

  9. return result

这个装饰器能够运行在普通函数上:

  1. @Timeit

  2. def func():

  3. time.sleep(1)

  4. return "invoking function func"

  5. if __name__ == '__main__':

  6. func() # output: elapsed time is 1.00044410133

但是运行在方法上会报错,为什么?

  1. class A(object):

  2. @Timeit

  3. def func(self):

  4. time.sleep(1)

  5. return 'invoking method func'

  6. if __name__ == '__main__':

  7. a = A()

  8. a.func() # Boom!

如果我坚持使用类装饰器,应该如何修改?

答案

使用类装饰器后,在调用func函数的过程中其对应的 instance 并不会传递给__call__方法,造成其mehtod unbound,那么解决方法是什么呢?描述符赛高

  1. class Timeit(object):

  2. 声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除


路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部