Follower me on GitHub

前言

写这个评注系统是因为最新写书, 想找个更顺畅的和编辑沟通的方式, 提高工作效率。 学Django的同学应该都访问过: http://djangobook.py3k.cn/ , 它和Djangobook官网 有个很重要的功能: 评注系统。在这里先向VCC致敬, 虽然很久没有继续维护,但是这个评注的功能还是很不错的。

我也翻了Djangobook的Git提交记录, 没有找到实现的方式。 而且最重要的是, 它是通过ReStructuredText生成的静态页面, 不符合我的需求。所以有了今天说的Aiglos

可以看Heroku上的Demo看看效果, 其中的文档使用了 https://github.com/GitbookIO/markdown

功能

  1. 在线浏览渲染的本地Markdown文件。
  2. 提供 http://djangobook.py3k.cn/2.0/ 那样的评注系统。
  3. 评注支持Markdown语法。

使用的技术

Flask: Web框架 Mako: 模板语言 Flask-Mako: Mako支持的Flask扩展 Flask-SQLAlchemy: SQLAlchemy的Flask扩展 mistune: Markdown渲染 cython: Python转化到C的编译器, 可以让mistune渲染更快

使用说明

❯ git clone https://github.com/dongweiming/aiglos
❯ cd aiglos
❯ virtualenv-2.7 venv
❯ source venv/bin/activate
❯ pip install -r requirements.txt
❯ touch local_settings.py  # 增加BOOK_DIR (Markdown文件存放目录), SQLALCHEMY_DATABASE_URI等配置
❯ gunicorn -w 3 run:app -b 0.0.0.0:8000

最近参考linty_fresh实现了一个webhook服务, 提PR自动检查Flake8, 当有代码风格问题的时候,并在对应位置发评论

项目地址是: gandalf

在公司内的Github企业版上, 已经用了一段时间, 比较稳定. 现在开源出来, 有兴趣的可以拿去^.^

这个项目也是我的学习asyncio的练手作品, 吐槽下Type Hints让代码显的好丑哇…

项目知识点

  1. Python3: 项目需要使用Python3, 建议使用Python3.5
  2. rq: 工作中有一些项目的版本库很大, 实际的检查时间也会长一些, 为了保证应用解耦和更好的提供支持, 使用rq作为任务队列
  3. aiohttp: 基于asyncio的http库, 用来调用github api, 获取对应pr信息
  4. pygit2: 使用官方模块实现Python版本的git版本控制功能, 它的安装比较麻烦, 但是官方文档讲的很清楚
  5. Flask: 作为webhook的服务框架

来几张截图看个效果:

配置

 cat gandalf/config.py
WORK_DIR = '/tmp/repositories'  # 设定克隆的项目版本库代码存放位置
FLAKE8_EXECUTABLE = '/usr/local/bin/flake8'  # 这个项目时Python3的,但是目前大部分应用还是Python2的, 所以需要Python2版本的flake8
HOST = '0.0.0.0'
PORT = 8080
DEBUG = False
REPORT_NO_MATCHING = False  # 没有在diff列表的文件的错误是否也报告
GITHUB_URL = 'http://github.com/'  # 行尾要加反斜杠
GITHUB_API_URL = 'https://api.github.com'  # 行尾不要加反斜杠
REPORT_CLOSEST = False # 错误出现在PR列出的文件中, 但是修改并不是此次PR中的diff里面是否报告
COMMENT_HEADER = ''  # 上述截图出现的emoji头部就是指定它, 我的设置是`COMMENT_HEADER = ':sparkles:Subject Bot:sparkles:'`


try:
    from local_settings import *
except ImportError:
    pass

配置webhook

需要在github的项目/组织设置页,找到Webhooks, 然后Add webhook

  1. Payload URL输入 http://192.168.1.1:28030/api/hooks # 或者你跑起来web服务的地址
  2. 选择事件 ,Let me select individual events. 然后勾选Pull Request

如图:

Enjoy it

应某出版社约, 最近一直在写一本Python Web开发的书. 暂时不发大纲全部的章节,主要涵盖如下方面的内容:

  1. 使用Python从零开始做一个完善的项目
  2. 源码级别分析产品过程中的各种知识点
  3. 站在运维,运维开发的角度讲解现在互联网Web应用的的方方面面
  4. 排错, 优化, 设计项目等

我清晰的知道都写些什么, 但是担心最后遗漏读者们有兴趣,关心的一些方面的内容, 特写本文. 本博客的读者如果有想法和建议, 欢迎和我交流.

开源了, 开源了

喜大普奔.

欢迎围观试用: CODE

再来一遍 CODE

想直接看效果的可以看 这里 或者拉到最下面.

可能很多人有点诧异, CODE不是已经开源了么? 是的, 2014年2月14日CODE的早期版本就开源到了github. 但是后来由于很多原因没有在做下去, 今天, 它真的开源了.

让我坚持下来的也是我想给外界看到豆瓣工程师文化的结晶, 这是一种情怀, 今天我想说说我和CODE的故事

CODE的意义

CODE为什么开源: 希望更多的人可以使用 CODE,希望更多的人可以一起开发 CODE。 - Code Team

市面上有gitlab, 有github企业版. 我们折腾一个这样的东西有什么意义呢? 以下是我的看法.

  1. CODE是一款豆瓣工程师自发组织, 基于我们自己的需要做出来的. 它是互联网公司程序员的需要而产生的, CODE也曾经给github的同仁们演示, 获得了很高的赞誉.
  2. 它并不是github的python克隆版, 但是有些地方却是和github殊途同归.
  3. 当产品发展到一定地步, 对这个版本控制工具会有更多的定制化需求, 这个时候会需要二次开发. 假如你是个ruby开发很多的公司, 用gitlab也不算个问题. 但是假如大家用非ruby的语言为主, 那么就很痛苦. ruby虽然在配置管理, web开发上面有一席之位, 但是没有python这么普遍. 同事们的参与局限性就多了很多.
  4. 假如你所在公司是python系, 或者爱好python系的, 那么CODE真的是一个很不错的选择. 它是永远免费的, 它是由国内python最大应用公司的工程师们开发, 质量有保证. 看代码的过程中也能学习到一些python的技巧, 豆瓣的玩法, 了解豆瓣的开发流程.
  5. 我一直觉得轮子是需要造的, 这个过程你能有造轮子的乐趣, 能力得到更多的提高, 而一直在用其他人的东西那么永远只会停留在这个程度上.
  6. 用CODE, 看CODE代码的时候, 仿佛可以看到那帮有情怀, 有工程师文化的同学们在讨论需求, code review… 我一直认为这种关系和友谊才是最好的团队具有的

情怀

好吧, 啥是情怀呢?

情怀就是以心灵的满足而不是功利的得失作为自己的行为标准的一种品质。 一件没什么用的事,还是要去做,也许只因为我喜欢,也许只因为它看起来很美 – 知乎@宋老末

「我坚信程序员都是有情怀的. 」

我决定继续这件事, 到现在已经4个月有余. 这个过程里面经历蛮多, 比如我经历着从技术转型做管理, 部门问题多多, 人员也在我强力介入下也流动蛮大的 -。-; 我也要花很大的精力陪女儿; 我一直也在不断的给自己充电, 我现在也要开始写书了… 做了TL, 唯一的感觉就是时间不够用, 我是个蛮有洁癖的人, 以前做普通工程师的时候按期完成我职责范围内的就好了, 现在责任大了, 看着产品线的sentry里那么多的报错, 看着Trello里面堆积那么多的card还没有机会做… 尤其在我使用一种新的管理风格有关, 让我倍敢压力, 非常辛苦.

要不是xTao不断催促, 可能还要拖期.

是什么支撑我的情怀?

除了眼前的苟且,还有诗和远方 - 知乎@戴晓溪

我和CODE

告诉你们个小秘密, 我来豆瓣其实也是和CODE有很大的关系的… 在这里感谢@xTao和邢老师.

这一切是为什么捏?

话说那是13年下半年, 我的前公司从svn转到了gitlab. 我们在内部搭建了一个gitlab服务器. 各个产品线的代码都开始往上面迁移, 我不得不说它是市面上非常好的开源选择. 但是过了一段时间我就发现了问题:

我是python系的, 我有时候对它是不满意的, 有想法二次开发的.

这里我提一点, 很多人都说: “哎呀不要局限于编程语言, 不要去争论xx是宇宙第一语言”. 我的观点是, 只有0.1%的天才+4.9%的有天赋, 能力很强的人是可以这么说的. 剩下的95%都是在给自己学的不好找个理由和慰藉罢了. 想要走在金字塔尖就需要有执念, 否则只能沦落到打打嘴炮的地步.

我曾经尝试一边翻着《Ruby元编程》一边去读gitlab的源码, 想尝试定制它. 努力了差不多一个月放弃了. 原因无二, 这种临时报佛脚去玩转一个大公司北京, 多位大牛参与的开源项目的必然结果.

很痛苦, 但是内心又多有不甘, 于是决定做一个大事: 用python造个gitlab的轮子:

  1. 样式扒gitlab
  2. 根据gitlab的路由方式添加url
  3. 使用pygit2作为git后端

做起来才知道, 这是一个非常浩大的工程, 对于我当时的技术能力来说是个非常大的挑战. 我汲取前后端知识就基本直接用在这个项目上了.

有一天, 我产生了放弃的念头.

之前我对豆瓣也没有什么特别的感觉. 直到这天我看到清风在 C2D2 的分享

http://segmentfault.com/a/1190000000410324 http://www.infoq.com/cn/articles/douban-code-2years http://www.infoq.com/cn/presentations/tools-love-knot-of-engineer-culture

在遥远的豆瓣, 有这样一帮人和我有同样的想法. 我称他们为geek. 这是我向往的地方呀. 于是, 我决定去豆瓣

CODE开源不久, 我就到了豆瓣.

非常遗憾, 我进来的时候, CODE的核心开发大多离开了豆瓣. 我没有机会和他们一起做CODE. CODE功能也接近稳定, 心情蛮失落的我只是修了几十个bug. 加一些功能, 比如:

  1. 鼠标放在团队上也会hover一个team的card
  2. telchar - 类似quora的qlint
  3. 鼠标放在emoji会悬浮图片的放大版本
  4. 项目的guidelines

等等.

我本想拿下CODE全部的徽章, 但是给我颁徽章的人们却不在了.

CODE的未来

我会保证CODE会一直做下去. 但是单个人的能力精力有限, 我欢迎更多的公司都来用CODE, 帮助它变得更好. 也欢迎更多的同学参与进来.

未来CODE会做以下几件事情(不断补充中)

  1. 完善CODE的功能 - 现在放出来, 跑起来了. 但是预计还会有很多坑
  2. 增加初始化脚本, 填充数据
  3. 修复travis-ci
  4. 国际化 - 现在code里面有很多中文, 需要英文能力很高的同学一起来做
  5. 重构 - 有很多功能都是需要重构甚至重写的
  6. 其他方面的尝试

截图时间

前言

什么? 你已经很了解python了? 好.

我们开始做个测验. 下面有12个题目. 填个空, 让这个代码片段变的可能.

先做个例子

例子1:

>>> x, y = ???
>>> x + y == y + x
False

其中有个???. 把它替换成什么就可以让这段代码成立呢?

揭晓答案:

>>> x, y = [0], [1]
>>> x + y == y + x
False

这个还是蛮简单的. 好继续

例子2:

>>> x = ???
>>> x < x
True

答案呢?

如果使用python内置的数据结构, 确实是不可能的. 唯一可以硬造一个例子

>>> x = type("", (), {"__lt__": lambda a, b: True})()
>>> x < x
True

但是这里不需要这么复杂的去想trick出结果, 只考虑python已经实现的设计

发考卷

  1. 难度3星
>>> x, y = ???
>>> min(x, y) == min(y, x)
False
  1. 难度4星
>>> x = ???
>>> len(set(list(x))) == len(list(set(x)))
False
  1. 难度3星
>>> x, s = ???
>>> s.add(x)
>>> type(x) in map(type, s)
False
  1. 难度3星
>>> x, y = ???
>>> x < y and all(a >= b for a, b in zip(x, y))
True
  1. 难度4星
>>> x, y = ???
>>> sum(0 * x, y) == y
False
  1. 难度5星
>>> x = ???
>>> min(x) == min(*x)
False
  1. 难度3星
>>> x, y, z = ???
>>> x * (y * z) == (x * y) * z
False
  1. 难度3星
>>> x, y, z = ???
>>> x * (y * z) == (x * y) * z
False
  1. 难度4星
>>> x, y = ???
>>> y > max(x) and y in x
True
  1. 难度5星
>>> x, y = ???
>>> any(x) and not any(x + y)
True
  1. 难度3星
>>> x, y = ???
>>> x.count(y) <= len(x)
False
  1. 难度5星
>>> x = ???
>>> all(filter(None, x))
False
  1. 难度4星
>>> x, a, b, c = ???
>>> max(x) < max(x[a:b:c])
True

答案呢

这是最近我觉得蛮有趣的一个项目 pywat

上面的评星是我加上去. 也体现了我做这些题目花费的精力和时间:

3星: 很快就想到, 实验出来了 4星: 花了蛮长时间, 终于找到答案了 5星: 最后实在找不倒答案, 看了答案恍然大悟啊啊啊啊

你能做到什么程度呢?

请慎重点击: 答案地址

前言

对我来说, 以前每次面试是我审视自己, 检验自己的一种方式. 每次准备面试, 以及被面试官问住的时候才会发现, 其实我python我学的还不够好; 工作中也是, 可以从其他的同事那里获得成长. 但是我今天说的是, 我也在自己总结和思考最佳实践这件事.

我想很多人都会有意识的去读一些PEP(Python Enhancement Proposals). 了解语言设计者当时的考虑, 这些文案也是经过很长时间的讨论最后才实施的. 既然想用好这门语言, 必然需要理解设计之美. 比如我听说gvanrossum使用emacs作为编辑器, 我也使用emacs, 就是希望我可以更贴近一些python

本文根据 The Best of the Best Practices (BOBP) Guide for PythonKhan’s style-guides中对于开发中一些事物的理解和看法, 有出至PEP, 也有一些python界知名开发者, 我加入了一些我自己的理解和看法.

价值观

“Build tools for others that you want to be built for you.” - Kenneth Reitz (requests等知名库作者)

你自己都不想用的东西做出来有什么意义呢?

“Simplicity is alway better than functionality.” - Pieter Hintjens (ZeroMQ)

我对函数式编程的看法一直是看场景, 甚至于我经常会对比性能, 义无反顾的使用性能最好的, 但是代码又不难懂和繁琐的

“Fit the 90% use-case. Ignore the nay sayers.” - Kenneth Reitz

程序员都有完美主义情怀, 但是其实往往我们是在偏激的看事情 - 用户其实不case

“Beautiful is better than ugly.” - PEP 20

开发参考

“Explicit is better than implicit” - PEP 20

不要留坑, 我经常看到一些复杂的代码, 这些代码的作者写的时候明显知道自己在做什么, 但是别人很难维护和看懂. 所以我对自己的职业的基本要求就是: 那天我离职了, 后来接手的人不会经常骂我

“Readability counts.” - PEP 20

“Anybody can fix anything.” - Khan’s style-guides

我现在更多不是代码炫技, 我经常思考的怎么让最少的代码, 最简单的设计结构满足当前需求, 也能给未来一段时间里也有扩展性

Fix each broken window (bad design, wrong decision, or poor code) as soon as it is discovered.

我们改bug有个原则 - 测试要覆盖到出bug的地方. 每个人内心都有很高的代码质量的要求

“Now is better than never.” - PEP 20

明日复明日, 明日何其多. 我们在代码review的时候, 问题需要在提出的时候就去改, 永远不会说下一次再说, 因为下一次大多时候是没有下一次了

Test ruthlessly. Write docs for new features.

Even more important that Test-Driven Development–Human-Driven Development

一些细节

PEP8

很多人是排斥的, 假如你想让未来部门有自己的风格, 习惯. 让新人马上上手接受, PEP8是一个非常明智的选择

文件开头

新的文件的开头需要加一些docstring. 描述文件的作用, 编辑者, 修改原因和日期等帮助阅读者的描述.

不要添加#!/usr/bin/python(除非这个文件未来是一个可执行的文件), copyright, __author__或者其他内容.

第一行建议添加# coding-utf-8

命名

  1. Variables, functions, methods, packages, modules

    lower_case_with_underscores

  2. Classes and Exceptions

    CapWords

  3. Protected methods and internal functions

    _single_leading_underscore(self, …)

  4. Private methods

    __double_leading_underscore(self, …)

  5. Constants

    ALL_CAPS_WITH_UNDERSCORES

  6. Avoid one-letter variables (esp. l, O, I).

    永远不要使用没有意义的单字符作为变量名

PS: 这点可以折中, 假如一个代码块代码逻辑很清晰, 而 这个短的便令也只是过程中的一个间接变量之类的情况下是可以接受的

Good or Bad

列举一些正确和错误的用法.

Avoid redundant labeling.

# Good
import audio

core = audio.Core()
controller = audio.Controller()

# Bad
import audio

core = audio.AudioCore()
controller = audio.AudioController()

不要使用重复意义的标签

Prefer “reverse notation”.

# Good
elements = ...
elements_active = ...
elements_defunct = ...

# Bad
elements = ...
active_elements = ...
defunct_elements ...

Avoid getter and setter methods.

# Good
person.age = 42

# Bad
person.set_age(42)

Indentation

永远不要Tab和空格混用. 使用4个空格作为python缩进

Imports

Import entire modules instead of individual symbols within a module.

PS: 这个时候可以参考tornado的代码用法.

比如现在有这样一个包

$ tree
└── canteen
    ├── __init__.py
    ├── sessions.py
# Good
import canteen
import canteen.sessions
from canteen import sessions

# Bad
from canteen import get_user  # Symbol from canteen/__init__.py
from canteen.sessions import get_session  # Symbol from canteen/sessions.py

PS: 除非这个第三方模块的文档显式的要求这些写

Splitting tricky lines

# Bad:
badge_name = badges.topic_exercise_badges.TopicExerciseBadge.name_for_topic_key_name(self.key().name())
# Good:
badge_name = (badges.topic_exercise_badges.TopicExerciseBadge
              .name_for_topic_key_name(self.key().name()))

# Bad:
self.redirect("/class_profile?selected_graph_type=%s&coach_email=%s&graph_query_params=%s" %
    (self.GRAPH_TYPE, urllib.quote(coach.email), urllib.quote(urllib.quote(self.request.query_string))))
# Good:
self.redirect(
    "/class_profile?selected_graph_type=%s&coach_email=%s"
    "&graph_query_params=%s" % (
        self.GRAPH_TYPE,
        urllib.quote(coach.email),
        urllib.quote(urllib.quote(self.request.query_string))))

我添加的规则

from … import …

# Bad
from aa import alonglonglonglonglong, alonglonglonglonglonglonglonglonglong, \
               alonglonglonglonglonglong

# Good
from aa import (alonglonglonglonglong, alonglonglonglonglonglonglonglonglong,
                alonglonglonglonglonglong)
from aa import (alonglonglonglonglong, alonglonglonglonglonglonglonglonglong,
    alonglonglonglonglonglong, alonglonglonglonglonglonglong,
    alonglonglonglonglonglong2)  # Good。 当引入的函数/类/变量很多时, 也可以选择空 4 个空格的方式, 而不需要和首行的左括号后对齐

相对引用(relative import) 和 绝对引用(absolute import)

$cat xx/models/user/consts.py  # 如果想引用这个变量
TMP = 1

$cat xx/views/user.py
from xx.models.user.consts import TMP  # recommended。

# 假如模块层级>=3。 比如 xx/models/user/consts.py 就在根目录下的第 3 级。 如果其他当前目录下源文件需要调用它的内容。 也可以选择相对引用
$cat xx/models/user/main.py  # 需要和 consts.py 在一个目录下才可以
from consts import TMP  # Bad
from .consts import TMP  # Good

# 而且只能在包内相对引用。 包外都需要绝对引用

前言

昨天翻到了一本在github开源的书: Intermediate Python. 就有了此文, 梳理了一下一些之前翻到的对python语言细节点的答案, 博文等.

英文的

super

Python’s super() considered super!

rhettinger是python核心开发者. 这篇博文也是讲super最好最深入的博文了.

装饰器

Understanding Python Decorators

如果你还没有经常性的用装饰器, 你就要思考你的工作需求是不是的太简单了, 或者该考虑下这种AOP模式的开发的作用了

元类

What is a metaclass in Python? Metaclasses Demystified

元类是python高阶语法. 合理的使用可以减少大量重复性的代码.

防御性编程中的LBYL和EAFP

Try/catch or validation for speed?

这其实就是事先检查和异常处理2个方式的讨论

__new__ 和 __init__

Python (and Python C API): new versus init

这也是一个常见的面试题.

self

Python “self” keyword

但是注意标题. 其实self不是一个关键词. 这里知识帮助你理解self的用意

协程和并发

A Curious Course on Coroutines and Concurrency

生成器

Generator Tricks for Systems Programmers

python开发必读

Code Like a Pythonista: Idiomatic Python

unicode必读

Unicode In Python, Completely Demystified

之前我曾经非常困惑于各种unicode报错

exec和eval

Be careful with exec and eval in Python

我的观点是从来都不要用exec/eval

python性能贴士

PerformanceTips Python Performance Tips, Part 1 Python Performance Tips, Part 2

描述符

How-To Guide for Descriptors

python隐藏特性

Hidden features of Python

设计模式

python-patterns

初级python进阶文档

Intermediate and Advanced Software Carpentry in Python

这个文档不是非常难, 甚至有点过时. 但是涵盖了python的方方面面. 非常有助于开拓视野, 更了解python

中(译)文

如何理解Python关键字yield

What does the yield keyword do in Python 如何理解Python关键字yield

yield 是python语言里面让初学者困惑的关键词之一. 可以参考这2个理解让你对yield入门. 并且之后在正确的场景下使用

迭代器(Iterator)与生成器(Generator)的区别

Difference between Python’s Generators and Iterators 迭代器(Iterator)与生成器(Generator)的区别

这个是很常见的面试问题.

设计模式入门

写给Python初学者的设计模式入门

所谓设计模式其实就是经过总结、优化的,对我们经常会碰到的一些编程问题的可重用解决方案. 其实有时候会发现沃恩日常工作中的一些思考就是设计模式

python设计模式- 我写的. 供参考.

描述符

Descriptor HowTo Guide Python描述器引导(翻译)

descriptor是python高阶的特性, 可以了解下python设计的优雅. PS: 里面也提到了类方法和静态方法的区别

使用断言(assert)的正确场景

Python 使用断言的最佳时机 Best practice for Python Assert

Python track: python idioms Python的惯例

提高编码效率

Improving Your Python Productivity 提高你的Python编码效率

Stackoverflow上的Python问题精选

Stackoverflow上的Python问题精选

Python魔法方法指南

Python魔法方法指南

Python高级编程 - 我写的

Python高级编程

洪强宁的ppt.

Python高级编程(二)

PS: 这个 和上一个没有任何次序关系

前言

今天在微博上被私信, 聊了好久的关于python面试的事情. 其实感觉蛮经常的和很多人在聊这个话题. 尤其是建了一个python学习交流群之后, 群里讨论的, 私聊我的, 问的比较多的真的有python面试相关的. 总结起来大概以下几种:

  1. python面试最常用的面试题有哪些?
  2. 某个面试题感觉回答的不好, 问怎么回答比较好.
  3. 有什么面试经验可以分享.
  4. 豆瓣面试一般问什么 - 我是不可能泄题的, 以后不要这么可爱了……

突然觉得有必要专门聊聊python面试这件事儿. 随便分享下我的故事.

工作了几年, 必然面过几家. 我不是面霸, 但是也肯定有感觉特别奇葩的, 没对上眼的, 完虐我的,励志的, 让我感动的. 让我感恩的.

来个趣事儿

国内python圈有名的公司不多. 12年的时候觉得要从运维开发转型为真正的开发, 面试了某知名公司S. 一直到现在我还觉得他的面试模式很好 - 初步筛选之后会发面试题, 2个题目任选其一, 一周做好. 当时python刚学会一年多, 反正蛮辛苦的还是做完了. 后来接到一面的电话. 当时觉得他们的工作环境特别好, 想着能留下来该多好. 这个组的面试风格比较特别 - 三个组员一起来面试, 轮流问问题, 有技术的, 有个人兴趣的, 有职业规划的. 为什么说这个呢? 这是我工作以来影响最深的面试, 甚至说对我未来影响很大, 一直到现在我都非常感谢他们. 现在我每次面试其他人, 都要花的时间比较多, 希望挖掘更多的候选人的优点, 给更多的建议和帮助. 总是想起他们对我的建议. 我们说了什么呢?

我清楚的记得几个事情

  1. 看我简历学了熟悉django. 问我django请求到响应的流程. 没有回答上来. 其中一个面试官给我解释下流程.
  2. 问了一些python语法, 应用场景, 但是我大都没有深入了解, 事后我挨个查了这些知识点, 发现其实我只是学会了皮毛
  3. 无意间聊到了编辑器, 我说用vim, 但是只是会用:q, :%s这有限的几个. 他们说这么久了, 就没有想想应该花时间好好的学习下, 提高工作效率么? 很难想象我是怎么开发的.. 说了很多, 我都有点完全被鄙视的想快点结束这个面试了.

面试其实时间还挺长的. 最后我问了我每次面试结束都会问的问题: 你们对我有什么建议?

他们说了这么几点, 和大家共勉

  1. 他们觉得我买了好多书, 想看想学的很多, 但是都没有深入. 建议我砍掉一半的兴趣, 把这些时间专注于做其中的几件
  2. 一个领域学习1,2个就好了. 比如web框架. 只要学好django或者flask, 理解原理. 用什么框架已经不重要了
  3. 好好学习一个编辑器. 驾驭好它, 让它提高你的工作效率.
  4. python学的不够深入, 建议我在细节上一个一个的抠, 力争弄清楚每一个, 积少成多

说到这里, 好像没啥有趣的.. 对吧

14年初, 在我面试豆瓣前, 我特意给S当时虐我的三人之一发邮件. 希望获得一个面试机会. 大概因为之前特意吐槽了S开源的一个项目还对我有兴趣, 很快又拿到了面试题. 这次的要难很多, 我还拖了一天交卷. 但是还是获得了一面的机会. 然后一直到最后谈薪资.

不同的是, 当时三人已经只剩下一个. 面试过程也没再问python问题(面试题答案应该已经证明了).

当时我已经准备好虐他们了….

  1. 我真的不再关注那么多的领域, 当时买的好多书甚至因为搬家给卖掉了却出来没看过
  2. 我曾经专注的看过python标准库和一些项目的代码, 给很多开源项目贡献代码, 甚至给python标准库贡献了代码
  3. 我都不用vim, 改用emacs了
  4. 后来面试豆瓣时候也基本没有问python问题, 可见我python能力还好 (*^ー^)

还没完….

以前一面某S的一个工程师. 聊着聊着.

他说: 你知不知道有个叫做XXX的? 我说: 我就是. 他说: 啊! 我还在想我会不会遇到你呢? 我说: 嘿嘿, 你如愿了 他说: 之前听别人说过你. balabala

机会是给有准备的人的. 不是python工作不好找, 只是没学好. 当时去S面试是个下午, 那天阳光和煦, 阳光照在我们那个屋子里面的玻璃桌上面, 面试的气氛很轻松. 当时觉得他们每个人对自己做的事情,对python都非常了解, 你是不是也想去这样的环境呢? 那么努力吧..

我来豆瓣也是一个励志的故事, 但是有点脱题了, 我们开始说python面试吧

我推崇的面试方式

这个更适合面试官来看

  1. 上面提到的, 决定要不要一面, 先发面试题来做, 看题目功能实现, 代码风格, 注释等和团队文化匹配度决定要不要一面, 更少的减少无用面试时间
  2. 知道创宇有一道爬虫的面试题写在博客里面, 想去的人把题做完发给他们就好了. 这道题确实不错. python掌握不好的确实做的会比较吃力, 也会直接暴露细节点掌握情况, 也可能会留下惊喜. 这样模式的题目也是一个筛选合适人才的办法

候选人应该做好哪些技术准备呢?

网上可以搜到一些面试题, 找了一些还不错的链接列出来

http://programmers.stackexchange.com/questions/21917/python-interview-questions
https://github.com/sigmavirus24/python-interview-questions
https://gist.github.com/xiangzhuyuan/7454001522d275021b2d
https://github.com/ContinuumIO/interview-questions
https://github.com/Flowerowl/python_articles
http://marselester.com/preparation-to-python-interview.html
https://github.com/zachwill/cracking-the-coding-interview
http://www.bogotobogo.com/python/python_interview_questions.php
https://www.quora.com/What-are-good-Python-interview-questions
https://www.reddit.com/r/Python/comments/1knw7z/python_interview_questions
https://github.com/1st/interview/blob/master/python.md

还有2个中文:

https://github.com/taizilongxu/interview_python
https://gist.github.com/prim/3e7f814187c715541ef2

毕竟我也是面试官, 就不划定那些是常见问题了. 防止我的主观意见对于未来影响面试者的评价公正性. 而且我也要说一点, 我也不评论上述文章中的答案的正确性了. 大家还是需要在面试前先做些查询和研究了

用心

  1. 去某公司面试前, 或者立志要去该公司. 最好先了解公司用到的python相关的技术栈, 这样可以有针对的准备相关内容
  2. 针对性的准备想要做的职位的python技能需求. 比如面试运维开发, 多准备系统, 数据库, 配置管理相关的知识, 比如web框架(除非了解到该职位需要)
  3. 及时关注python技能最新用法, 或者推荐用法. 多了解python3的趋势, 有可能会被面试官问到.
  4. 有个github账号. 能把自己的想法实践出来的python项目, 这样就多了了解你的机会. 可能在面试中就会少问你对应的技术点

前言

算来学会python已经4年有余, 使用它作为我的工作语言也3年了. 这个过程中我读过一些书, 看了很多人的博客. 也读了一些开源项目的代码, 但是尤其重要的是和同事在一起得到的进步. 一直到现在我都有习惯了解python, 提高自己的python能力

说到idiomatic. python有自己独特的语法和习惯. 而实现同样功能的代码不用的人呢也会使用不同的方式. 写出来的代码内容也有非常大的区别, 但是总是会有一个是更好的, idiomatic的写法. 今天突然翻到了一个我之前一直维护的keynote. 这里面记录了我总结和从其他的ppt或者代码里看到更优美的写法. 其中有些已经放在python3中, 说明这样的功能确实是程序员蛮有用的. 我整理了一下. 来给大家分享下.

PS: 这些是编程的思维, 举一反三, 再适合的时候利用上.

循环列表, 直到找到符合的结果, 没有结果返回一个默认值

通常这样:

a = -1
for i in range(1, 10):
    if not i % 4:
        a = i
        break
# a = 4

更好的写法:

a = ''
a = next((i for i in range(1, 10) if not i % 4), -1)
# a = 4

执行调用直到某种情况

通常这样:

blocks = []
while True:
    block = f.read(32)
    if block == '':
        break
    blocks.append(block)

更好的写法:

from functools import partial
blocks = []
for block in iter(partial(f.read, 32), ''):
    blocks.append(block)

标记区分

def find(seq, target):
    found = False
    for i, value in enumerate(seq):
        if value == target:
            found = True
            break
    if not found:
        return -1
    return i

更好的写法:

def find(seq, target):
    for i, value in enumerate(seq):
        if value == target:
            break
    else:
        return -1
    return i

threading.Lock

lock = threading.Lock()
lock.acquire()

try:
    print 'Critical section 1'
    print 'Critical section 2'
finally:
    lock.release()

其实是这样的:

lock = threading.Lock()

with lock:
    print 'Critical section 1'
    print 'Critical section 2'

忽略抛出的异常

try:
    os.remove('somefile.tmp')
except OSError:
    pass
with ignored(OSError):
    os.remove('somefile.tmp')

就算用python2, 我也强烈建议把这样的函数放在项目里

@contextmanager
def ignored(*exceptions):
    try:
        yield
    except exceptions:
        pass

如果你使用python3.4或以上可以使用标准库的 contextlib.suppress

class suppress:
    def __init__(self, *exceptions):
        self._exceptions = exceptions
    def __enter__(self):
        pass
    def __exit__(self, exctype, excinst, exctb):
        return exctype is not None and issubclass(exctype, self._exceptions)

直接把输出存进文件中

with open('help.txt', 'w') as f:
    oldstdout = sys.stdout
    sys.stdout = f
    try:
        help(pow)
    finally:
        sys.stdout = oldstdout

同样使用python3.4以上可以使用

with open('help.txt', 'w') as f:
    with redirect_stdout(f):
        help(pow)

redirect_stdout是这样的:

@contextmanager
def redirect_stdout(fileobj):
    oldstdout = sys.stdout
    sys.stdout = fileobj
    try:
        yield fieldobj
    finally:
        sys.stdout = oldstdout

最简单的缓存

通常这样实现缓存:

def web_lookup(url, saved={}):
    if url in saved:
        return saved[url]
    page = urllib.urlopen(url).read()
    saved[url] = page
    return page

可以这样写

@cache
def web_lookup(url):
    return urllib.urlopen(url).read()

def cache(func):
    saved = {}
    @wraps(func)
    def newfunc(*args):
        if args in saved:
            return newfunc(*args)
        result = func(*args)
        saved[args] = result
        return result
    return newfunc

前言

豆瓣内部有一些基础设施我认为做得都很好, 比如bridge和p. 一是身为用户的体验, 一个是我以开发的角度会去想我能不能做的更好.

这些基础设施凝聚了豆瓣早期的工程师文化的精髓, 至今还在影响着每个豆瓣的工程师.

今天我们聊到的是p - 一个文件上传托管服务, 一个被严重低估了的工具, 它已经被清风老师拆分出来不需要跑在dae上. 而我今天推荐的就是我用react+es6plus+webpack重写的版本 r

为什么说我认为被低估呢? 目前star也才五十几. 当时开始用p. 我对效果非常惊艳.

如果你很好奇是不是也会这么认为. 可以先看个heroku的demo. 因为连接了heroku的远程cleardb(mysql的封装), 上传反映略慢. 而本地会很流畅. 主要看效果吧.

r的用途

身在互联网工作, 会经常有这样的需求

  1. 希望上传后的文件(包含图片)可以被永久存放.
  2. 想在github(CODE)上, 能方便的引用一些bug截图(甚至在多个地方引用).
  3. 希望上传的文件(包含图片), 能有一个比较好的预览页(包含文件大小, 文件类型, 上传时间等), 下载地址, 也能生成短链接, 二维码
  4. 希望能对某上传的图片传一些参数做对应的缩放和剪切
  5. 身在互联网, 页面太low, 效果不炫, 作为工程师, 用起来是会有抵制心情的.

对. r(p) 就可以做这些事.

用到的其他技术

Flask, SQLAlchemy, Mako, Pillow