Write Python like a Pro

Context Managers

If you have a function do_sth(), before invoking this method, it needs connect to Database and get filelock. And code maybe like this:

  try:
    db.connect()
    getfilelock()
    do_sth()
  except:
    ...
  finally:
    releasefilelock()
    db.close()

What if do_sth be called at many palces? If filelock is now don't need, code should be rewrited at each palce whendo_sth is called. 
After wasting a whole afternoon rewriting the code, you find it's useful to have a function to do this. Then code will be:

  try:
    prepare()
    do_sth()
  except:
    ...
  finally:
    close()

Each palce do_sth invoked is full of prepare/close. And both of them has no relation with bussiness logic. It makes the code longer and longer.
Although you don't care about the cofusion you may have when you see these code after 2 months(because the only one line of bussiness logic code is hidden in seven lines of non-business code), you should be friendly to those who review your code. A funciton more than 500 lines is horrible. I think writing code is an action to get abstraction from complex logic, if there is no abstraction in code, it's not coding but translating. What prepare/close doed indeed? They are preapre or release an environment to do_sth, that is context.
Python use with statement to manage context.

  class A():
    def do_sth(self):
      pass

    def __enter__(self):
      db.connect()
      getfilelock()
      return self

    def __exit__(self, type, value, traceback):
      releasefilelock()
      db.close()

  with A() as a:
    a.do_sth()

Now the reviewer will only see

  with A() as a:
    a.do_sth()

Context manager is uesd explictly. Bussiness logic and impelement are splited.

Explicit is better than implicit. Simple is better than complex.

Anthor common way is using __del__

  class A():
      def __init__(self):
          db.connect()
          getfilelock()

      def __del__(self, type, value, traceback):
          releasefilelock()
          db.close()

  a =  A()
  a.do_sth()

The good part of this way is no need of wiring with. But it's not a explicit context manager. To GC languages like Python or Java, there is no way to invoke a destructor method. Although object has leaved the scope, if it was not cleaned by GC, the resource it takes will not be released.
If the resource is database connect, close lately is acceptable, but to resource like mutex, we need with statement to release it immediately.

Generation

A function with yield is a generator. Generation maintains a context to eval result when it is need. For example:

  for i in range(100000):
      do_sth()

It creates an array of 1-100000 before do_sth which will make a waste of memory. Another loop with xrange:

  for i in xrange(100000):
      do_sth()

That is what we know in C++, do_sth once and then i++, loops.

  for(int i = 0; i < 100000; i++) {
      do_sth()
  }

So xrange will use less memory than range.

    def fetchmany(self, *args, **kwargs):
        '''
           A generator to fetch data.
        '''
        cur = self._conn.cursor()
        numRows = 200
        try:
            cur.execute(*args, **kwargs)
            self._conn.commit()
        except Exception as e:
            self.logger.error(str(e))
            self._conn.rollback()
            return
        while True:
            rows = cur.fetchmany(numRows)
            if rows:
                yield rows
            else:
                cur.close()
                return

for rows in fetchmany(sql):
    do_sth_with_rows(rows)

fetchmany is a generator, and a generator is iteratable. Only 200 rows will be taken in a patch, not all of the results.

Generator can also be used to make a co-routine.

import random

def get_data():
    """Return 3 random integers between 0 and 9"""
    return random.sample(range(10), 3)

def consume():
    """Displays a running average across lists of integers sent to it"""
    running_sum = 0
    data_items_seen = 0

    while True:
        data = yield
        data_items_seen += len(data)
        running_sum += sum(data)
        print('The running average is {}'.format(running_sum / float(data_items_seen)))

def produce(consumer):
    """Produces a set of values and forwards them to the pre-defined consumer
    function"""
    while True:
        data = get_data()
        print('Produced {}'.format(data))
        consumer.send(data)
        yield

if __name__ == '__main__':
    consumer = consume()
    consumer.send(None)
    producer = produce(consumer)

    for _ in range(10):
        print('Producing...')
        next(producer)

More useful cases in Tornado.

Decorator

Decorator is a useful syntax sugar to split implement detail. For example

  begin = time.time()
  do_sth()
  end = time.time()
  print 'do sth used %s second' % (end-begin)

In above code, profile code is mixed in logic code.
By decorator

def logtime(func):
    @wraps(func)
    def wrapper(*args, **kwds):
        start_time = time.time()
        ret = func(*args, **kwds)
        use_time = time.time() - start_time
        if use_time > 1.0:
            logging.info("%s use %s s", func.__name__, use_time)
        return ret
    return wrapper

@logtime
def do_sth():
  ...

do_sth()

When do_sth be invoked, the caller don't need to know about logtime. There is also a @ used in Java. But that is aannotation, it's not run-time but a complie time reflect.
That has no relation with decorator in Python.

Unicode

Here are some code to show the relation with unicode and str

>>> a = '我'
>>> a
'\xe6\x88\x91'
>>> type(a)
<type 'str'>

>>> b = '我'.decode('utf-8')
>>> b
u'\u6211'
>>> type(b)
<type 'unicode'>

>>> b.encode('utf-8')
'\xe6\x88\x91'
>>> b.encode('gbk')
'\xce\xd2'

In Python2, str is byte array and unicode is charset code of the character.

时间: 2024-12-09 20:18:57

Write Python like a Pro的相关文章

《Python数据科学实践指南》——1.2 Python解释器

1.2 Python解释器 由于Python是一门开源语言,所以只要愿意,任何人都可以为其实现一个解释器.目前官方解释器CPython是绝对主流,如果读者有兴趣,可以了解一下其他的版本,比如支持JIT(即时编译)的PyPy,可以把Python编译成C语言的Cython,拥有notebook这样友好.方便编程界面的IPython等.本书会使用官方解释器CPython进行讲解,并且还会使用到一些第三方的库,本节也将介绍一下如何在主流的操作系统中安装必要的软件. 1.2.1 Mac OS X系统 如果

《Python数据科学实践指南》一1.2 Python解释器

1.2 Python解释器 由于Python是一门开源语言,所以只要愿意,任何人都可以为其实现一个解释器.目前官方解释器CPython是绝对主流,如果读者有兴趣,可以了解一下其他的版本,比如支持JIT(即时编译)的PyPy,可以把Python编译成C语言的Cython,拥有notebook这样友好.方便编程界面的IPython等.本书会使用官方解释器CPython进行讲解,并且还会使用到一些第三方的库,本节也将介绍一下如何在主流的操作系统中安装必要的软件. 1.2.1 Mac OS X系统 如果

《Python数据科学实践指南》——1.2节Python解释器

1.2 Python解释器由于Python是一门开源语言,所以只要愿意,任何人都可以为其实现一个解释器.目前官方解释器CPython是绝对主流,如果读者有兴趣,可以了解一下其他的版本,比如支持JIT(即时编译)的PyPy,可以把Python编译成C语言的Cython,拥有notebook这样友好.方便编程界面的IPython等.本书会使用官方解释器CPython进行讲解,并且还会使用到一些第三方的库,本节也将介绍一下如何在主流的操作系统中安装必要的软件.1.2.1 Mac OS X系统如果读者使

10 个平板电脑上的 Python 编辑器

本文介绍 10 个可在 iOS 或 Android 平板电脑上的 Python 编程环境.Python 开发者可通过这些工具实现随时随地编码,蛋疼抑或爽极? Pythonista Python 声称将实现 "在你的iPad或iPhone实现Python的禅" ,不到比萨的价格你就可以购买的 Pythonista 并开始编码. 这对新手也很有用,如果你不是一个 Python 开发者,但想学习这门脚本语言,Pythonista 是你可以负担得起的方式. 特性: 全功能的代码编辑器,包含内建

可爱的Python:Python IDE测评

David Mertz 介绍了 6 种 Python 集成开发环境,并比较了其特性.平台和稳定性.他发现 -- 或许只是无意中对开放源代码模块的测试 -- 免费产品似乎都比商业产品优秀. 前几周,我有幸对一些 Python 开发环境做了一次全新的试用(或者说是首次尝试).这样很可能会涉及从实际尝试"最佳文本编辑器,附加命令行"方法到 Python 开发,而对于更复杂的 Python 集成开发环境 (IDE) 在 Python 讨论网站上有详尽的内容. 对 Python IDE 的整体印

python selenium,PhantomJS运用 抓取滚动条滚动加载的页面, js动作操作,模拟登陆

1.运用 #!/usr/bin/python #encoding=utf-8 import sys from selenium import webdriver reload(sys) sys.setdefaultencoding( "utf-8" ) driver = webdriver.PhantomJS(executable_path='/home/lhy/phantomjs-1.9.8-linux-x86_64/bin/phantomjs') driver.get("

旅行时通过树莓派和 iPad Pro 备份图片

旅行中备份图片 - 组件 介绍 我在很长的时间内一直在寻找一个旅行中备份图片的理想方法,把 SD 卡放进你的相机包会让你暴露在太多的风险之中:SD 卡可能丢失或者被盗,数据可能损坏或者在传输过程中失败.比较好的一个选择是复制到另外一个介质中,即使它也是个 SD 卡,并且将它放到一个比较安全的地方去,备份到远端也是一个可行的办法,但是如果去了一个没有网络的地方就不太可行了. 我理想的备份步骤需要下面的工具: 用一台 iPad pro 而不是一台笔记本.我喜欢轻装旅行,我的大部分旅程都是商务相关的(

python脚本实现集群检测和管理

场景是这样的:一个生产机房,会有很多的测试机器和生产机器(也就是30台左右吧),由于管理较为混乱导致了哪台机器有人用.哪台机器没人用都不清楚,从而产生了一个想法--利用一台机器来管理所有的机器,记录设备责任人.设备使用状态等等信息....那么,为什么选择python,python足够简单并且拥有丰富的第三方库的支持. 最初的想法 由于刚参加工作不久,对这些东西也都没有接触过,轮岗到某个部门需要做出点东西来(项目是什么还没情况,就要做出东西来,没办法硬着头皮想点子吧)... 本想做一个简单点的自动

用 Python 和 Numpy 实现音频数字指纹特征识别

本文讲的是用 Python 和 Numpy 实现音频数字指纹特征识别, 我第一次用 Shazam 的时候,简直惊呆了.除了 GPS 功能和从楼梯摔下仍然没坏之外,能用一段音频片段识别歌曲是我所见过我手机能做到的最不可思议的事了.识别是通过一个叫音频特征识别的过程来实现的,例子包括: Shazam SoundHound / Midomi Chromaprint Echoprint 经过几个周末在学术论文和代码中求索,我想出了一个基于 Python 语言开发的,开源的音频特征识别项目,名字叫 Dej