Python的递归调用栈的深度有限制, 可以通过sys.getrecursionlimit()查看。
尾递归在很多语言中都可以被编译器优化, 基本都是直接复用旧的执行栈, 不用再创建新的栈帧, 原理上其实也很简单, 因为尾递归在本质上看的话递归调用是整个子过程调用的最后执行语句, 所以之前的栈帧的内容已经不再需要, 完全可以被复用。
需要注意的是, 一定记住尾递归的特点是: 递归调用是整个子过程调用的最后一步, 否则就不是真正的尾递归了, 如下就不是真正的尾递归, 虽然递归调用出现在尾部:
def fib(n):
if n == 0:
return 0
elif n == 1:
继续阅读 »
为了响应总菊的要求, 互联网智能电视盒子必须接入牌照方的播控平台, 登陆时必须认证一下, 认证通过才让你接入我们的服务, 否则你就呵呵了。我们有两个接口会代理一下用户的请求, 大致逻辑是:
客户端首先请求接口A, 会把MAC地址带过来, 接口A的handler会做一些校验, 然后根据一些其他的参数, 重新组装一个请求去访问牌照方的接口, 根据参数的不同会请求不同的接口
牌照方会根据用户的MAC地址和其他信息返回鉴权的结果, 返回里面会有某个字段表示成功还是失败
接口A对牌照方的接口做些校验, 没问题的返给客户端, 客户端根据鉴权结果, 成功则继续进行剩下的鉴权,失败则终止请求, 用户可能就无法使用剩下的服务
看起来是个很简单的只
继续阅读 »
Linux里的IO多路复用是有效提高IO效率的技术。主要有select、poll、epoll三种。
select
select调用的函数接口是:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
参数说明:
nfds: fdset中最大描述符值加1, fdset是一个位数组, 大小为__FD_SETSIZE(1024), 位数组的每一位表示该描述符是否被检查
readfds, writefds, exceptfds: 三个位数组, 非别对应监听不同类型读写及错误事件的描述符。
继续阅读 »
协程是用户态内的,或者准确点说是线程内部的一种上下文切换技术,由于协程切换是在用户态下完成的,所以省去了线程切换时频繁出入内核态的资源开销,可以形成一种很高效的协作式并发技术。
这个简短的视频介绍了一些有关协程、并发之类的东西,很有意义。
Coroutines, event loops, and the history of Python generators
从里面学习到两种很好的协程的调度方式。把代码拿过来分享一下。
Coroutine trampoline
这种方式下的协程调度比较好理解,就是从一个初始状态开始,一条执行线索不断的在多个协程之间切换,就好像多个协程协作完成一项任务。
代码:
def co_tramp
继续阅读 »
"可迭代对象"与"迭代器"
Python中迭代器指的是实现了__iter__协议与next()方法的对象,其中__iter__协议中返回对象自身(self),next()方法每次返回单一元素,直至所有元素遍历结束,抛出'StopIteration'异常结束。
可迭代对象是一种更宽泛的定义,只要对象实现了__iter__协议,返回一个迭代器(并不像迭代器一样必须返回自身self)用来遍历自己的元素集合,那这个对象就是可迭代的对象,也意味着可以直接通过for item in obj...的方式遍历。
iter(a) is iter(a)?
>>a = [1, 2, 3]
>>iter(a) is iter(a) #(1)
>>F
继续阅读 »
客户端提出搞一个日志上传的接口,方便向服务端提交日志,研究了一下,决定用Nginx嵌入Lua的方式搞。
Lua是一个可以嵌入到Nginx配置文件中的动态脚本语言,从而可以在Nginx请求处理的任何阶段执行各种Lua代码。业余时间使用过,感觉小巧轻快,代码风格和Python一样简洁优雅。在Nginx中内嵌Lua,需要你重新编译安装Nginx,加上ngx_lua模块,同时需要安装LuaJIT,可以看看这篇文章"Nginx与Lua"。
安装好相关的模块后,Nginx配置如下:
location ~ /upload { # 调用的路由
# 转到后台处理URL
upload_pass /uploadHandle;
继续阅读 »
9月19号参加了北京的PyCon2015,有众多互联网公司参加,而且云计算类的公司颇多,足以看出Python在云计算领域的应用之广。
虽然会上广告很多,但也不乏干货:
1.美团云的分享: 简单语言构建复杂系统 幻灯
2.Splunk首席工程师丁来强的分享: Python高效函数式编程 幻灯
3.SpeedyCloud工程师汪尊: Python的多线程与多进程
4.豆瓣的分享: Pidl(Python Interface Description Language)
同时,可以看到Tornado这个异步非阻塞高性能轻量级服务器在互联网内有着大范围的应用,Python的胶水特性在云计算领域是粘和多模块的有力武器。
PyCon
继续阅读 »
Python的"类型-对象"体系实现的简洁而优雅,"元类"-"类"-"实例对象"自上而下,层次分明。
以下是关键的几个点:
1.一切(函数,类等)皆对象(object)
2.变量名只是对象的引用
3.object类是所有类(对象)的最终父类,但object不是任何类的子类,这是对1的解释
4.type既是object类的实例,也是object类的子类
5.object作为一个类对象,她的类也是type
6.object和type是鸡和蛋的关系
7.type很重要,在整个体系中,真正干活的就是type
8.元类就是类(一切皆对象)的类
9.1)type负责生成'类'(对象),是最终元类(调用:type(class_n
继续阅读 »
有些时候你的项目中难免需要一些全局唯一的对象,这些对象大多是一些工具性的东西,在Python中实现单例模式并不是什么难事。以下总结几种方法:
使用类装饰器
使用装饰器实现单例类的时候,类本身并不知道自己是单例的,所以写代码的人可以不care这个,只要正常写自己的类的实现就可以,类的单例有装饰器保证。
def singleton(cls):
instances = {}
def _wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
r
继续阅读 »
Memcached作为高性能的分布式内存对象缓存系统,在web服务里应用较广,和高性能的异步非阻塞服务器Tornado搭配起来可以大幅提高服务端的性能。
应用Memcached缓存热点请求结果
我们给客户端提供api,通过json来返回http请求的结果,一般Web服务都是如此。由于用的是Tornado,所以逻辑上大概长这样:
一个请求对应一个RequestHandler对象,RequestHandler类通过定义get/post方法来处理http请求,结果会通过write方法写到一个write_buffer里,最终有flush方法负责将write_buffer里的结果返回给客户端。
缓存的话,我们一般是这样:
从Torn
继续阅读 »