Upgrade to Pro — share decks privately, control downloads, hide ads and more …

QCon2010-douban-py4web

 QCon2010-douban-py4web

洪教授的经验分享

Zoom.Quiet

April 28, 2010
Tweet

More Decks by Zoom.Quiet

Other Decks in Programming

Transcript

  1. Python • Python is a programming language that lets you

    work more quickly and integrate your systems more effectively. You can learn to use Python and see almost immediate gains in productivity and lower maintenance costs. (via http://python.org/)
  2. षؿ࿡ࢮ import os from collections import defaultdict d = defaultdict(int)

    for dirpath, dirnames, filenames in os.walk('.'): for filename in filenames: path = os.path.join(dirpath, filename) ext = os.path.splitext(filename)[1] d[ext] += len(list(open(path))) for ext, n_lines in d.items(): print ext, n_lines ๤࠹۲ᇕე࿽֥ս઒ྛඔ: 13ྛ
  3. ሧჷپڶ • Battery Included: ѓሙ९ଽᇂ200+ଆॶ • PyPI: 9613 packages currently

    • ຩ઎/ඔऌ९/ም૫/Ⴓ༤/॓࿐࠹ෘ/νಆ/໓ Чԩ৘/... • easily extensible
  4. web.py import web urls = ( '/(.*)', 'hello' ) app

    = web.application(urls, globals()) class hello: def GET(self, name): if not name: name = 'World' return 'Hello, ' + name + '!' if __name__ == "__main__": app.run() http://webpy.org/
  5. Flask import flask import Flask app = Flask(__name__) @app.route("/<name>") def

    hello(name): if not name: name = 'World' return 'Hello, ' + name + '!' if __name__ == "__main__": app.run() http://flask.pocoo.org/
  6. Why so many Python web frameworks? • Because you can

    write your own framework in 3 hours and a total of 60 lines of Python code. • http://bitworking.org/news/ Why_so_many_Python_web_frameworks
  7. doctest def cube(x): """ >>> cube(10) 1000 """ return x

    * x def _test(): import doctest doctest.testmod() if __name__ == "__main__": _test()
  8. numpy >>> from numpy import * >>> A = arange(4).reshape(2,

    2) >>> A array([[0, 1], [2, 3]]) >>> dot(A, A.T) array([[ 1, 3], [ 3, 13]]) http://numpy.scipy.org/
  9. ipython $ ipython -pylab In [1]: X = frange(0, 10,

    0.1) In [2]: Y = [sin(x) for x in X] In [3]: plot(X, Y) http://numpy.scipy.org/
  10. ipython $ ipython -pylab In [1]: X = frange(0, 10,

    0.1) In [2]: Y = [sin(x) for x in X] In [3]: plot(X, Y) http://numpy.scipy.org/
  11. virtualenv $ python go-pylons.py --no-site-packages mydevenv $ cd mydevenv $

    source bin/activate (mydevenv)$ paster create -t new9 helloworld http://virtualenv.openplans.org/ Էࡹ၂۱ۄ֥࣪aۯ৖֥pythonߌ࣢
  12. >>> import this The Zen of Python, by Tim Peters

    Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. يၲğঠႧݽ http://bit.ly/pyzencn Ⴊૅ഻ႿԘੑ ૼਔ഻Ⴟ߳೥ ࡥࢱ഻Ⴟگᄖ گᄖ഻Ⴟ਱੹ ы௜഻Ⴟళส ࡗۯ഻Ⴟࣅ՘ ॖ؀ྟޓᇗေ ࠧьࡌࢹห২֥ൌႨྟᆭ଀đ္҂ॖ ິМᆃུܿᄵ ҂ေЇಸ෮Ⴕհ༂đԢ٤୆ಒקླေ ᆃဢቓ
  13. In the face of ambiguity, refuse the temptation to guess.

    There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those! ֒թᄝ؟ᇕॖିđ҂ေӇ൫ಀ҉ҩ ط൞࣐ਈᅳ၂ᇕđቋݺ൞ື၂၂ᇕ ૼཁ֥ࢳथٚσ ෙಖᆃѩ҂ಸၞđၹູ୆҂൞ Python ᆭڳ ቓ္ྸݺݖ҂ቓđ֌҂ࡌන෬ࣼ׮ ൭ߎ҂ೂ҂ቓ ೂݔ୆໭مཟದ૭ඍ୆֥ٚσđପ ड़ק҂൞၂۱ݺٚσĠّᆭၧಖ ଁ଀ॢࡗ൞၂ᇕध૳֥৘୑đ໡ૌ ႋ֒؟ࡆ০Ⴈ
  14. Simple is better than complex class HelloWorld { public static

    void main(String args[]) { System.out.println("Hello World!"); } }
  15. Readability counts • ఼ᇅॶ෪ࣉđીႵ{}ބend • ીႵٮࢳ֥ሳژ (except "@" for decorators)

    if limit is not None and len(ids)>limit: ids = random.sample(ids, limit)
  16. TOOWTDI • There (should be) Only One Way To Do

    It. • vs. Perlish TIMTOWTDI (There Is More Than One Way To Do It)
  17. TOOWTDI • There (should be) Only One Way To Do

    It. • vs. Perlish TIMTOWTDI (There Is More Than One Way To Do It) a = [1, 2, 3, 4, 5] b = [] for i in range(len(a)): b.append(a[i]*2)
  18. TOOWTDI • There (should be) Only One Way To Do

    It. • vs. Perlish TIMTOWTDI (There Is More Than One Way To Do It) a = [1, 2, 3, 4, 5] b = [] for i in range(len(a)): b.append(a[i]*2)
  19. TOOWTDI • There (should be) Only One Way To Do

    It. • vs. Perlish TIMTOWTDI (There Is More Than One Way To Do It) a = [1, 2, 3, 4, 5] b = [] for i in range(len(a)): b.append(a[i]*2) b = [] for x in a: b.append(x*2)
  20. TOOWTDI • There (should be) Only One Way To Do

    It. • vs. Perlish TIMTOWTDI (There Is More Than One Way To Do It) a = [1, 2, 3, 4, 5] b = [] for i in range(len(a)): b.append(a[i]*2) b = [] for x in a: b.append(x*2)
  21. TOOWTDI • There (should be) Only One Way To Do

    It. • vs. Perlish TIMTOWTDI (There Is More Than One Way To Do It) b = [x*2 for x in a]
  22. MEMCACHED_ADDR = ['localhost:11211'] from local_config import * config.py MEMCACHED_ADDR =

    [ 'frodo:11211', 'sam:11211', 'pippin:11211', 'merry:11211', ] local_config.py
  23. MEMCACHED_ADDR = ['localhost:11211'] from local_config import * config.py MEMCACHED_ADDR =

    [ 'frodo:11211', 'sam:11211', 'pippin:11211', 'merry:11211', ] local_config.py ໓ࡱ଀ުሗ҂ູ.pyൈđ ္ॖ൐Ⴈexec
  24. class GroupUI(object): def new_topic(self, request): if self.group.can_post(request.user): return new_topic_ui(self.group) else:

    request.response.set_status(403, "Forbidden") return error_403_ui(msg="ӮູཬቆӮჴҌିؿ๎") def join(self, request): if self.group.can_join(request.user): ... class Group(object): def can_post(self, user): return self.group.has_member(user) def can_join(self, user): return not self.group.has_banned(user)
  25. class GroupUI(object): @check_permission('post', msg="ӮູཬቆӮჴҌିؿ๎") def new_topic(self, request): return new_topic_ui(self.group) @check_permission('join',

    msg="҂ିࡆೆཬቆ") def join(self, request): ... class Group(object): def can_post(self, user): return self.group.has_member(user) def can_join(self, user): return not self.group.has_banned(user)
  26. decorator def print_before_exec(func): def _(*args, **kwargs): print "decorated" return func(*args,

    **kwargs) return _ @print_before_exec def double(x): print x*2 double(10)
  27. decorator def print_before_exec(func): def _(*args, **kwargs): print "decorated" return func(*args,

    **kwargs) return _ @print_before_exec def double(x): print x*2 double(10) ൻԛğ decorated 20
  28. class check_permission(object): def __init__(self, action, msg=None): self.action = action self.msg

    = msg def __call__(self, func): def _(ui, *args, **kwargs): f = getattr(ui.perm_obj, 'can_' + action) if f(req.user): return func(ui, *args, **kwargs) raise BadPermission(ui.perm_obj, self.action, self.msg) return _
  29. class check_permission(object): def __init__(self, action, msg=None): self.action = action self.msg

    = msg def __call__(self, func): def _(ui, *args, **kwargs): f = getattr(ui.perm_obj, 'can_' + action) if f(req.user): return func(ui, *args, **kwargs) raise BadPermission(ui.perm_obj, self.action, self.msg) return _
  30. class check_permission(object): def __init__(self, action, msg=None): self.action = action self.msg

    = msg def __call__(self, func): def _(ui, *args, **kwargs): f = getattr(ui.perm_obj, 'can_' + action) if f(req.user): return func(ui, *args, **kwargs) raise BadPermission(ui.perm_obj, self.action, self.msg) return _
  31. class check_permission(object): def __init__(self, action, msg=None): self.action = action self.msg

    = msg def __call__(self, func): def _(ui, *args, **kwargs): f = getattr(ui.perm_obj, 'can_' + action) if f(req.user): return func(ui, *args, **kwargs) raise BadPermission(ui.perm_obj, self.action, self.msg) return _
  32. class check_permission(object): def __init__(self, action, msg=None): self.action = action self.msg

    = msg def __call__(self, func): def _(ui, *args, **kwargs): f = getattr(ui.perm_obj, 'can_' + action) if f(req.user): return func(ui, *args, **kwargs) raise BadPermission(ui.perm_obj, self.action, self.msg) return _
  33. class check_permission(object): def __init__(self, action, msg=None): self.action = action self.msg

    = msg def __call__(self, func): def _(ui, *args, **kwargs): f = getattr(ui.perm_obj, 'can_' + action) if f(req.user): return func(ui, *args, **kwargs) raise BadPermission(ui.perm_obj, self.action, self.msg) return _
  34. class GroupUI(object): @check_permission('post', msg="ӮູཬቆӮჴҌିؿ๎") def new_topic(self, request): return new_topic_ui(self.group) @check_permission('join',

    msg="҂ିࡆೆཬቆ") def join(self, request): ... class Group(object): def can_post(self, user): return self.group.has_member(user) def can_join(self, user): return not self.group.has_banned(user)
  35. def send_notification_mail(email, subject, body): msg = MSG_SEND_MAIL + '\0' +

    email + '\0' + subject + '\0' + body mq.put(msg) def async_worker(): msg = mq.get() msg = msg.split('\0') cmd = msg[0] if cmd == MSG_SEND_MAIL: email, subject, body = msg[1:] fromaddr = '[email protected]' email_body = make_email_body(fromaddr, email, subject, body) smtp = smtplib.SMTP('mail') smtp.sendmail(fromaddr, email, email_body) elif cmd == MSG_xxxx: ... elif cmd == MSG_yyyy: ...
  36. @async def send_notification_mail(email, subject, body): fromaddr = '[email protected]' email_body =

    make_email_body(fromaddr, email, subject, body) smtp = smtplib.SMTP('mail') smtp.sendmail(fromaddr, email, email_body)
  37. def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__

    mod[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod[fname](*a, **kw)
  38. def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__

    mod[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod[fname](*a, **kw)
  39. def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__

    mod[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod[fname](*a, **kw)
  40. def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__

    mod[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod[fname](*a, **kw)
  41. def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__

    mod[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod[fname](*a, **kw)
  42. def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__

    mod[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod[fname](*a, **kw)
  43. def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__

    mod[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod[fname](*a, **kw)
  44. def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__

    mod[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod[fname](*a, **kw)
  45. def get_latest_review_id(): review_id = mc.get('latest_review_id') if review_id is None: review_id

    = exc_sql("select max(id) from review") mc.set('latest_review_id', review_id) return review_id
  46. def cache(key): def deco(func): def _(*args, **kwargs): r = mc.get(key)

    if r is None: r = func(*args, **kwargs) mc.set(key, r) return r return _ return deco
  47. def cache(key): def deco(func): def _(*args, **kwargs): r = mc.get(key)

    if r is None: r = func(*args, **kwargs) mc.set(key, r) return r return _ return deco
  48. def get_review(id): key = 'review:%s' % id review = mc.get(key)

    if review is None: # cache miss id, author_id, text = exc_sql("select id, author_id, text from review where id=%s", id) review = Review(id, author_id, text) mc.set(key, review) return review ೂݔcache keyླေ׮෿ളӮ଻Ĥ
  49. ླေ׮෿ളӮ֥cache keyھೂޅཿ decoratorĤ @cache('review:{id}') def get_review(id): id, author_id, text =

    exc_sql("select id, author_id, text from review where id=%s", id) return Review(id, author_id, text)
  50. def cache(key_pattern, expire=0): def deco(f): arg_names, varargs, varkw, defaults =

    inspect.getargspec(f) if varargs or varkw: raise Exception("not support varargs") gen_key = gen_key_factory(key_pattern, arg_names, defaults) def _(*a, **kw): key = gen_key(*a, **kw) r = mc.get(key) if r is None: r = f(*a, **kw) mc.set(key, r, expire) return r return _ return deco
  51. def cache(key_pattern, expire=0): def deco(f): arg_names, varargs, varkw, defaults =

    inspect.getargspec(f) if varargs or varkw: raise Exception("not support varargs") gen_key = gen_key_factory(key_pattern, arg_names, defaults) def _(*a, **kw): key = gen_key(*a, **kw) r = mc.get(key) if r is None: r = f(*a, **kw) mc.set(key, r, expire) return r return _ return deco
  52. def cache(key_pattern, expire=0): def deco(f): arg_names, varargs, varkw, defaults =

    inspect.getargspec(f) if varargs or varkw: raise Exception("not support varargs") gen_key = gen_key_factory(key_pattern, arg_names, defaults) def _(*a, **kw): key = gen_key(*a, **kw) r = mc.get(key) if r is None: r = f(*a, **kw) mc.set(key, r, expire) return r return _ return deco
  53. inspect.getargspec >>> import inspect >>> def f(a, b=1, c=2): ...

    pass ... >>> inspect.getargspec(f) ArgSpec(args=['a', 'b', 'c'], varargs=None, keywords=None, defaults=(1, 2)) >>> >>> >>> def f(a, b=1, c=2, *args, **kwargs): ... pass ... >>> inspect.getargspec(f) ArgSpec(args=['a', 'b', 'c'], varargs='args', keywords='kwargs', defaults=(1, 2))
  54. def cache(key_pattern, expire=0): def deco(f): arg_names, varargs, varkw, defaults =

    inspect.getargspec(f) if varargs or varkw: raise Exception("not support varargs") gen_key = gen_key_factory(key_pattern, arg_names, defaults) def _(*a, **kw): key = gen_key(*a, **kw) r = mc.get(key) if r is None: r = f(*a, **kw) mc.set(key, r, expire) return r return _ return deco
  55. def cache(key_pattern, expire=0): def deco(f): arg_names, varargs, varkw, defaults =

    inspect.getargspec(f) if varargs or varkw: raise Exception("not support varargs") gen_key = gen_key_factory(key_pattern, arg_names, defaults) def _(*a, **kw): key = gen_key(*a, **kw) r = mc.get(key) if r is None: r = f(*a, **kw) mc.set(key, r, expire) return r return _ return deco hint: • str.format in python 2.6: '{id}'.format(id=1) => '1' • dict(zip(['a', 'b', 'c'], [1, 2, 3])) => {'a': 1, 'b': 2, 'c': 3}
  56. def cache(key_pattern, expire=0): def deco(f): arg_names, varargs, varkw, defaults =

    inspect.getargspec(f) if varargs or varkw: raise Exception("not support varargs") gen_key = gen_key_factory(key_pattern, arg_names, defaults) def _(*a, **kw): key = gen_key(*a, **kw) r = mc.get(key) if r is None: r = f(*a, **kw) mc.set(key, r, expire) return r return _ return deco hint: • str.format in python 2.6: '{id}'.format(id=1) => '1' • dict(zip(['a', 'b', 'c'], [1, 2, 3])) => {'a': 1, 'b': 2, 'c': 3}
  57. def cache(key_pattern, expire=0): def deco(f): arg_names, varargs, varkw, defaults =

    inspect.getargspec(f) if varargs or varkw: raise Exception("not support varargs") gen_key = gen_key_factory(key_pattern, arg_names, defaults) def _(*a, **kw): key = gen_key(*a, **kw) r = mc.get(key) if r is None: r = f(*a, **kw) mc.set(key, r, expire) return r return _ return deco
  58. class Feed(object): def get_entries(self, limit=10): ids = exc_sqls("select id from

    entry where feed_id= %s order by id desc limit %s", (self.id, limit)) return [Entry.get(id) for id in ids] class FeedCollection(object): def get_entries(self, limit=10): mixed_entries = [] for feed in self.feeds: entries = feed.get_entries(limit=limit) mixed_entries += entries mixed_entries.sort(key=lambda e: e.id, reverse=True) return mixed_entries[:10]
  59. class Feed(object): def get_entries(self, limit=10): ids = exc_sqls("select id from

    entry where feed_id= %s order by id desc limit %s", (self.id, limit)) return [Entry.get(id) for id in ids] class FeedCollection(object): def get_entries(self, limit=10): mixed_entries = [] for feed in self.feeds: entries = feed.get_entries(limit=limit) mixed_entries += entries mixed_entries.sort(key=lambda e: e.id, reverse=True) return mixed_entries[:10]
  60. class Feed(object): def get_entries(self, limit=10): ids = exc_sqls("select id from

    entry where feed_id= %s order by id desc limit %s", (self.id, limit)) return [Entry.get(id) for id in ids] class FeedCollection(object): def get_entries(self, limit=10): mixed_entries = [] for feed in self.feeds: entries = feed.get_entries(limit=limit) mixed_entries += entries mixed_entries.sort(key=lambda e: e.id, reverse=True) return mixed_entries[:10]
  61. class Feed(object): def get_entries(self, limit=10): ids = exc_sqls("select id from

    entry where feed_id= %s order by id desc limit %s", (self.id, limit)) return [Entry.get(id) for id in ids] class FeedCollection(object): def get_entries(self, limit=10): mixed_entries = [] for feed in self.feeds: entries = feed.get_entries(limit=limit) mixed_entries += entries mixed_entries.sort(key=lambda e: e.id, reverse=True) return mixed_entries[:10] ඔऌ९Ұ࿘ྛඔ = len(self.feeds) * limit
  62. class Feed(object): def get_entries(self, limit=10): ids = exc_sqls("select id from

    entry where feed_id= %s order by id desc limit %s", (self.id, limit)) return [Entry.get(id) for id in ids] class FeedCollection(object): def get_entries(self, limit=10): mixed_entries = [] for feed in self.feeds: entries = feed.get_entries(limit=limit) mixed_entries += entries mixed_entries.sort(key=lambda e: e.id, reverse=True) return mixed_entries[:10] শٮ֥Entry.getඔ = len(self.feeds-1) * limit
  63. iterator and generator def fib(): x, y = 1, 1

    while True: yield x x, y = y, x+y def odd(seq): return (n for n in seq if n%2) def less_than(seq, upper_limit): for number in seq: if number >= upper_limit: break yield number print sum(odd(less_than(fib(), 4000000)))
  64. itertools • count([n]) --> n, n+1, n+2 • cycle(p) -->

    p0, p1, ... plast, p0, p1, ... • repeat(elem [,n]) --> elem, elem, elem, ... endless or up to n times • izip(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ... • islice(seq, [start,] stop [, step]) --> elements from seq[start:stop:step] • ... and more ...
  65. class Feed(object): def iter_entries(self): start_id = sys.maxint while True: entry_ids

    = exc_sqls("select id from entry where feed_id=%s and id<%s order by id desc limit 5", (self.id, start_id)) if not entry_ids: break for entry_id in entry_ids: yield Entry.get(entry_id) start_id = entry_ids[-1] class FeedCollection(object): def iter_entries(self): return imerge(*[feed.iter_entries() for feed in self.feeds]) def get_entries(self, limit=10): return list(islice(self.iter_entries(), limit))
  66. class Feed(object): def iter_entries(self): start_id = sys.maxint while True: entry_ids

    = exc_sqls("select id from entry where feed_id=%s and id<%s order by id desc limit 5", (self.id, start_id)) if not entry_ids: break for entry_id in entry_ids: yield Entry.get(entry_id) start_id = entry_ids[-1] class FeedCollection(object): def iter_entries(self): return imerge(*[feed.iter_entries() for feed in self.feeds]) def get_entries(self, limit=10): return list(islice(self.iter_entries(), limit))
  67. class Feed(object): def iter_entries(self): start_id = sys.maxint while True: entry_ids

    = exc_sqls("select id from entry where feed_id=%s and id<%s order by id desc limit 5", (self.id, start_id)) if not entry_ids: break for entry_id in entry_ids: yield Entry.get(entry_id) start_id = entry_ids[-1] class FeedCollection(object): def iter_entries(self): return imerge(*[feed.iter_entries() for feed in self.feeds]) def get_entries(self, limit=10): return list(islice(self.iter_entries(), limit))
  68. class Feed(object): def iter_entries(self): start_id = sys.maxint while True: entry_ids

    = exc_sqls("select id from entry where feed_id=%s and id<%s order by id desc limit 5", (self.id, start_id)) if not entry_ids: break for entry_id in entry_ids: yield Entry.get(entry_id) start_id = entry_ids[-1] class FeedCollection(object): def iter_entries(self): return imerge(*[feed.iter_entries() for feed in self.feeds]) def get_entries(self, limit=10): return list(islice(self.iter_entries(), limit))
  69. class Feed(object): def iter_entries(self): start_id = sys.maxint while True: entry_ids

    = exc_sqls("select id from entry where feed_id=%s and id<%s order by id desc limit 5", (self.id, start_id)) if not entry_ids: break for entry_id in entry_ids: yield Entry.get(entry_id) start_id = entry_ids[-1] class FeedCollection(object): def iter_entries(self): return imerge(*[feed.iter_entries() for feed in self.feeds]) def get_entries(self, limit=10): return list(islice(self.iter_entries(), limit))
  70. class Feed(object): def iter_entries(self): start_id = sys.maxint while True: entry_ids

    = exc_sqls("select id from entry where feed_id=%s and id<%s order by id desc limit 5", (self.id, start_id)) if not entry_ids: break for entry_id in entry_ids: yield Entry.get(entry_id) start_id = entry_ids[-1] class FeedCollection(object): def iter_entries(self): return imerge(*[feed.iter_entries() for feed in self.feeds]) def get_entries(self, limit=10): return list(islice(self.iter_entries(), limit)) ඔऌ९Ұ࿘ྛඔ = len(self.feeds) * 5 ~ len(self.feeds)*5 + limit -5
  71. class Feed(object): def iter_entries(self): start_id = sys.maxint while True: entry_ids

    = exc_sqls("select id from entry where feed_id=%s and id<%s order by id desc limit 5", (self.id, start_id)) if not entry_ids: break for entry_id in entry_ids: yield Entry.get(entry_id) start_id = entry_ids[-1] class FeedCollection(object): def iter_entries(self): return imerge(*[feed.iter_entries() for feed in self.feeds]) def get_entries(self, limit=10): return list(islice(self.iter_entries(), limit)) শٮ֥Entry.getඔ = 0
  72. class User(object): def __init__(self, id, username, screen_name, sig): self.id =

    id self.username = username self.screen_name = screen_name self.sig = sig user = User('1002211', 'hongqn', 'hongqn', "ϘϘ҃aϘϘ҃Ϙ҃ Ϙ҃Ć")
  73. $ python -m timeit -s ' > from user import

    user > from cPickle import dumps, loads > s = dumps(user, 2)' \ > 'loads(s)' 100000 loops, best of 3: 6.6 usec per loop $ python -m timeit -s ' > from user import user > from marshal import dumps, loads > d = (user.id, user.username, user.screen_name, user.sig) > s = dumps(d, 2)' 'loads(s)' 1000000 loops, best of 3: 0.9 usec per loop cPickle vs. marshal
  74. $ python -m timeit -s ' > from user import

    user > from cPickle import dumps, loads > s = dumps(user, 2)' \ > 'loads(s)' 100000 loops, best of 3: 6.6 usec per loop $ python -m timeit -s ' > from user import user > from marshal import dumps, loads > d = (user.id, user.username, user.screen_name, user.sig) > s = dumps(d, 2)' 'loads(s)' 1000000 loops, best of 3: 0.9 usec per loop cPickle vs. marshal 7П෎؇ิശ
  75. $ python -m timeit -s ' > from user import

    user > from cPickle import dumps, loads > s = dumps(user, 2)' \ > 'loads(s)' 100000 loops, best of 3: 6.6 usec per loop $ python -m timeit -s ' > from user import user > from marshal import dumps, loads > d = (user.id, user.username, user.screen_name, user.sig) > s = dumps(d, 2)' 'loads(s)' 1000000 loops, best of 3: 0.9 usec per loop cPickle vs. marshal 7П෎؇ิശ
  76. $ python -c ' > import cPickle, marshal > from

    user import user > print "pickle:", len(cPickle.dumps(user, 2)) > print "marshal:", len(marshal.dumps((user.id, \ > user.username, user.screen_name, user.sig), 2))' pickle: 129 marshal: 74 cPickle vs. marshal timeit 43%ॢࡗࢫസ
  77. $ python -c ' > import cPickle, marshal > from

    user import user > print "pickle:", len(cPickle.dumps(user, 2)) > print "marshal:", len(marshal.dumps((user.id, \ > user.username, user.screen_name, user.sig), 2))' pickle: 129 marshal: 74 cPickle vs. marshal timeit 43%ॢࡗࢫസ
  78. namedtuple from collections import namedtuple User = namedtuple('User', 'id username

    screen_name sig') user = User('1002211', 'hongqn', 'hongqn', sig="ϘϘ҃aϘϘ҃ Ϙ҃Ϙ҃Ć") user.username -> 'hongqn'
  79. __metaclass__ class User(tuple): __metaclass__ = NamedTupleMetaClass __attrs__ = ['id', 'username',

    'screen_name', 'sig'] user = User('1002211', 'hongqn', 'hongqn', sig="ϘϘ҃aϘϘ҃ Ϙ҃Ϙ҃Ć") s = marshal.dumps(user.__marshal__()) User.__load_marshal__(marshal.loads(s))
  80. from operator import itemgetter class NamedTupleMetaClass(type): def __new__(mcs, name, bases,

    dict): assert bases == (tuple,) for i, a in enumerate(dict['__attrs__']): dict[a] = property(itemgetter(i)) dict['__slots__'] = () dict['__marshal__'] = tuple dict['__load_marshal__'] = classmethod(tuple.__new__) dict['__getnewargs__'] = lambda self: tuple(self) argtxt = repr(tuple(attrs)).replace("'", "")[1:-1] template = """def newfunc(cls, %(argtxt)s): return tuple.__new__(cls, (%(argtxt)s))""" % locals() namespace = {} exec template in namespace dict['__new__'] = namespace['newfunc'] return type.__new__(mcs, name, bases, dict)
  81. descriptor • ၂۱ऎႵ__get__, __set__ࠇᆀ __delete__ٚم֥ؓའ class Descriptor(object): def __get__(self, instance,

    owner): return 'descriptor' class Owner(object): attr = Descriptor() owner = Owner() owner.attr --> 'descriptor'
  82. ӈႨ֥descriptor • classmethod • staticmethod • property class C(object): def

    get_x(self): return self._x def set_x(self, x): self._x = x x = property(get_x, set_x)
  83. class environ_getter(object): def __init__(self, key, default=None): self.key = key self.default

    = default def __get__(self, obj, objtype): if obj is None: return self return obj.get_environ(self.key, self.default) class HTTPRequest(quixote.http_request.HTTPRequest): for key in ['HTTP_REFERER', 'REMOTE_ADDR', 'SERVER_NAME', 'REQUEST_URI', 'HTTP_HOST']: locals()[key.lower()] = environ_getter(key) del key locals()
  84. class environ_getter(object): def __init__(self, key, default=None): self.key = key self.default

    = default def __get__(self, obj, objtype): if obj is None: return self return obj.get_environ(self.key, self.default) class HTTPRequest(quixote.http_request.HTTPRequest): for key in ['HTTP_REFERER', 'REMOTE_ADDR', 'SERVER_NAME', 'REQUEST_URI', 'HTTP_HOST']: locals()[key.lower()] = environ_getter(key) del key
  85. import httplib orig_connect = httplib.HTTPConnection.connect def _patched_connect(self): if HOSTS_BLOCKED.match(self.host): return

    _connect_via_socks_proxy(self) else: return orig_connect(self) def _connect_via_socks_proxy(self): ... httplib.HTTPConnection.connect = _patched_connect
  86. षؿߌ࣢ • щࠠఖ: Vim / Emacs / Ulipad • ϱЧܵ৘:

    subversion / mercurial / git • wiki/հ༂۵ሶ/ս઒ᛍফ: Trac • ӻ࿃ࠢӮ: Bitten
  87. Python Implementations • CPython http://www.python.org/ • Unlanden-Swallow http://code.google.com/p/unladen-swallow/ • Stackless

    Python http://www.stackless.com/ • IronPython http://ironpython.net/ • Jython http://www.jython.org/
  88. Python Implementations • CPython http://www.python.org/ • Unlanden-Swallow http://code.google.com/p/unladen-swallow/ • Stackless

    Python http://www.stackless.com/ • IronPython http://ironpython.net/ • Jython http://www.jython.org/ • PyPy http://pypy.org/