# python计数器 - Python的隐藏功能

## python提高效率 (20)

Python编程语言的鲜为人知的但有用的功能是什么？

• 尝试限制Python核心的答案。
• 每个答案一个功能。
• 给出一个示例和功能的简短描述，而不仅仅是文档的链接。
• 作为第一行使用标题标记该功能。

## Doctest : documentation and unit-testing at the same time.

Example extracted from the Python documentation:

``````def factorial(n):
"""Return the factorial of n, an exact integer >= 0.

If the result is small enough to fit in an int, return an int.
Else return a long.

>>> [factorial(n) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> factorial(-1)
Traceback (most recent call last):
...
ValueError: n must be >= 0

Factorials of floats are OK, but the float must be an exact integer:
"""

import math
if not n >= 0:
raise ValueError("n must be >= 0")
if math.floor(n) != n:
raise ValueError("n must be exact integer")
if n+1 == n:  # catch a value like 1e300
raise OverflowError("n too large")
result = 1
factor = 2
while factor <= n:
result *= factor
factor += 1
return result

def _test():
import doctest
doctest.testmod()

if __name__ == "__main__":
_test()
``````

## Named formatting

% -formatting takes a dictionary (also applies %i/%s etc. validation).

``````>>> print "The %(foo)s is %(bar)i." % {'foo': 'answer', 'bar':42}

>>> foo, bar = 'question', 123

>>> print "The %(foo)s is %(bar)i." % locals()
The question is 123.
``````

And since locals() is also a dictionary, you can simply pass that as a dict and have % -substitions from your local variables. I think this is frowned upon, but simplifies things..

New Style Formatting

``````>>> print("The {foo} is {bar}".format(foo='answer', bar=42))
``````

## 叙

They're the magic behind a whole bunch of core Python features.

When you use dotted access to look up a member (eg, xy), Python first looks for the member in the instance dictionary. If it's not found, it looks for it in the class dictionary. If it finds it in the class dictionary, and the object implements the descriptor protocol, instead of just returning it, Python executes it. A descriptor is any class that implements the `__get__` , `__set__` , or `__delete__` methods.

Here's how you'd implement your own (read-only) version of property using descriptors:

``````class Property(object):
def __init__(self, fget):
self.fget = fget

def __get__(self, obj, type):
if obj is None:
return self
return self.fget(obj)
``````

and you'd use it just like the built-in property():

``````class MyClass(object):
@Property
def foo(self):
return "Foo!"
``````

Descriptors are used in Python to implement properties, bound methods, static methods, class methods and slots, amongst other things. Understanding them makes it easy to see why a lot of things that previously looked like Python 'quirks' are the way they are.

Raymond Hettinger has an excellent tutorial that does a much better job of describing them than I do.

## 字典有一个get（）方法

`sum[value] = sum.get(value, 0) + 1`

for ... else语法（请参阅http://docs.python.org/ref/for.html

``````for i in foo:
if i == 0:
break
else:
print("i was never 0")
``````

``````found = False
for i in foo:
if i == 0:
found = True
break
print("i was never 0")
``````

``````def mygen():
"""Yield 5 until something else is passed back via send()"""
a = 5
while True:
f = (yield a) #yield a and possibly get f in return
if f is not None:
a = f  #store the new value
``````

``````>>> g = mygen()
>>> g.next()
5
>>> g.next()
5
>>> g.send(7)  #we send this back to the generator
7
>>> g.next() #now it will yield 7 until we send something else
7
``````

Interactive Interpreter Tab Completion

``````try:
except ImportError:
else:
import rlcompleter

>>> class myclass:
...    def function(self):
...       print "my function"
...
>>> class_instance = myclass()
>>> class_instance.<TAB>
class_instance.__class__   class_instance.__module__
class_instance.__doc__     class_instance.function
>>> class_instance.f<TAB>unction()
``````

You will also have to set a PYTHONSTARTUP environment variable.

Main messages :)

``````import this
# btw look at this module's source :)
``````

The Zen of Python, by Tim Peters

Flat is better than nested.
Sparse is better than dense.

Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
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!

Re-raising exceptions :

``````# Python 2 syntax
try:
some_operation()
except SomeError, e:
if is_fatal(e):
raise
handle_nonfatal(e)

# Python 3 syntax
try:
some_operation()
except SomeError as e:
if is_fatal(e):
raise
handle_nonfatal(e)
``````

The 'raise' statement with no arguments inside an error handler tells Python to re-raise the exception with the original traceback intact , allowing you to say "oh, sorry, sorry, I didn't mean to catch that, sorry, sorry."

If you wish to print, store or fiddle with the original traceback, you can get it with sys.exc_info(), and printing it like Python would is done with the 'traceback' module.

iter（）可以采用可调参数

``````def seek_next_line(f):
pass
``````

`iter(callable, until_value)`函数重复调用`callable`并产生结果，直到返回`until_value`

``````def draw_point(x, y):
# do some magic

point_foo = (3, 4)
point_bar = {'y': 3, 'x': 2}

draw_point(*point_foo)
draw_point(**point_bar)
``````

``````x=(n for n in foo if bar(n))
``````

``````for n in x:
``````

``````x = [n for n in foo if bar(n)]
``````

``````>>> n = ((a,b) for a in range(0,2) for b in range(4,6))
>>> for i in n:
...   print i

(0, 4)
(0, 5)
(1, 4)
(1, 5)
``````

``````>>> pattern = """
... ^                   # beginning of string
... M{0,4}              # thousands - 0 to 4 M's
... (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                     #            or 500-800 (D, followed by 0 to 3 C's)
... (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                     #        or 50-80 (L, followed by 0 to 3 X's)
... (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                     #        or 5-8 (V, followed by 0 to 3 I's)
... \$                   # end of string
... """
>>> re.search(pattern, 'M', re.VERBOSE)
``````

``````>>> p = re.compile(r'(?P<word>\b\w+\b)')
>>> m = p.search( '(((( Lots of punctuation )))' )
>>> m.group('word')
'Lots'
``````

``````>>> pattern = (
...     "^"                 # beginning of string
...     "M{0,4}"            # thousands - 0 to 4 M's
...     "(CM|CD|D?C{0,3})"  # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                         #            or 500-800 (D, followed by 0 to 3 C's)
...     "(XC|XL|L?X{0,3})"  # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                         #        or 50-80 (L, followed by 0 to 3 X's)
...     "(IX|IV|V?I{0,3})"  # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                         #        or 5-8 (V, followed by 0 to 3 I's)
...     "\$"                 # end of string
... )
>>> print pattern
"^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})\$"
``````

``````>>> def foo(x=[]):
...     x.append(1)
...     print x
...
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]
``````

``````>>> def foo(x=None):
...     if x is None:
...         x = []
...     x.append(1)
...     print x
>>> foo()
[1]
>>> foo()
[1]
``````

``````>>> re.compile("^\[font(?:=(?P<size>[-+][0-9]{1,2}))?\](.*?)[/font]",
re.DEBUG)
at at_beginning
literal 91
literal 102
literal 111
literal 110
literal 116
max_repeat 0 1
subpattern None
literal 61
subpattern 1
in
literal 45
literal 43
max_repeat 1 2
in
range (48, 57)
literal 93
subpattern 2
min_repeat 0 65535
any None
in
literal 47
literal 102
literal 111
literal 110
literal 116
``````

``````>>> re.compile("""
^              # start of a line
\[font         # the font tag
(?:=(?P<size>  # optional [font=+size]
[-+][0-9]{1,2} # size specification
))?
\]             # end of tag
(.*?)          # text between the tags
\[/font\]      # end of the tag
""", re.DEBUG|re.VERBOSE|re.DOTALL)
``````

Decorators允许在另一个函数中包装函数或方法，该函数可以添加功能，修改参数或结果等。您可以在函数定义的上方一行写入装饰器，并以“at”符号（@）开头。

``````>>> def print_args(function):
>>>     def wrapper(*args, **kwargs):
>>>         print 'Arguments:', args, kwargs
>>>         return function(*args, **kwargs)
>>>     return wrapper

>>> @print_args
>>> def write(text):
>>>     print text

>>> write('foo')
Arguments: ('foo',) {}
foo
``````

Nested list comprehensions and generator expressions:

``````[(i,j) for i in range(3) for j in range(i) ]
((i,j) for i in range(4) for j in range(i) )
``````

These can replace huge chunks of nested-loop code.

To add more python modules (espcially 3rd party ones), most people seem to use PYTHONPATH environment variables or they add symlinks or directories in their site-packages directories. Another way, is to use *.pth files. Here's the official python doc's explanation:

"The most convenient way [to modify python's search path] is to add a path configuration file to a directory that's already on Python's path, usually to the .../site-packages/ directory. Path configuration files have an extension of .pth, and each line must contain a single path that will be appended to sys.path. (Because the new paths are appended to sys.path, modules in the added directories will not override standard modules. This means you can't use this mechanism for installing fixed versions of standard modules.)"

``````a = [1,2,3,4,5]
>>> a[::2]  # iterate over the whole list in 2-increments
[1,3,5]
``````

``````>>> a[::-1]
[5,4,3,2,1]
``````

``````from __future__ import braces
``````