主要留言:)

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

解封了

《Python的禅》,Tim Peters著

美丽胜于丑陋。
显式比隐式好。
简单胜于复杂
复杂胜于复杂
扁平比嵌套好。
稀疏胜于密集
可读性很重要。
特殊情况不足以打破规则。
虽然实用性胜过纯度。
错误永远不应该默默传递。
除非明确沉默。
面对模棱两可,拒绝猜测的诱惑。应该有一个-最好只有一个-明显的方法来做到这一点。虽然一开始这种方式可能并不明显,除非你是荷兰人。现在总比没有好。
虽然现在从来没有比更好的了。
如果实现很难解释,那是个坏主意。
如果实现很容易解释,那可能是个好主意。
命名空间是一个很棒的想法-让我们做更多的!

列表理解

列表解析

比较更传统的(没有列表理解):

foo = []for x in xrange(10):if x % 2 == 0:foo.append(x)

到:

foo = [x for x in xrange(10) if x % 2 == 0]

创建生成器对象

如果你写

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

你可以拿出生成器并将其分配给x。现在这意味着你可以

for n in x:

这样做的好处是,你不需要中间存储,如果你需要的话

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

在某些情况下,这可能会导致显著的加速。

您可以将许多if语句附加到生成器的末尾,基本上复制嵌套的for循环:

>>> 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)

装饰师

装饰师允许将函数或方法包装在另一个函数中,该函数可以添加功能、修改参数或结果等。您在函数定义上方写了一行装饰器,以“at”符号(@)开头。

示例显示了一个print_args装饰器,它在调用它之前打印装饰函数的参数:

>>> 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

可读正则表达式

在Python中,您可以将正则表达式拆分为多行,命名匹配项并插入注释。

详细语法示例(来自潜入Python):

>>> 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)

示例命名匹配(来自正则表达式HOWTO

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

由于字符串文字连接,您还可以在不使用re.VERBOSE的情况下详细编写正则表达式。

>>> 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})$"

嵌套列表推导和生成器表达式:

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

这些可以替换大量嵌套循环代码。

模块运算符中的Getter函数

模块operator中的函数attrgetter()itemgetter()可用于生成快速访问函数,用于排序和搜索对象和字典

第6.7在Python库文档中

将值发送到生成器函数。例如具有此功能:

def mygen():"""Yield 5 until something else is passed back via send()"""a = 5while True:f = (yield a) #yield a and possibly get f in returnif 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 generator7>>> g.next() #now it will yield 7 until we send something else7

能够替换文件删除、文件打开等内容-直接操作语言库。当测试。时,这是一个巨大的优势。您不必将所有内容包装在复杂的容器中。只需替换一个函数/方法即可。这也称为猴子补丁。

>>> x=[1,1,2,'a','a',3]>>> y = [ _x for _x in x if not _x in locals()['_[1]'] ]>>> y[1, 2, 'a', 3]


"locals()['_[1]']"是正在创建的列表的"秘密名称"。当正在构建的列表状态影响后续构建决策时非常有用。

切片运算符中的步骤参数。例如:

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

特例x[::-1]是“x反转”的有用习语。

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

隐式连接

>>> print "Hello " "World"Hello World

当你想要使一个长文本适合脚本中的几行时很有用:

hello = "Greaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hello " \"Word"

hello = ("Greaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hello ""Word")

您可以使用财产使您的类接口更加严格。

class C(object):def __init__(self, foo, bar):self.foo = foo # read-write propertyself.bar = bar # simple attribute
def _set_foo(self, value):self._foo = value
def _get_foo(self):return self._foo
def _del_foo(self):del self._foo
# any of fget, fset, fdel and doc are optional,# so you can make a write-only and/or delete-only property.foo = property(fget = _get_foo, fset = _set_foo,fdel = _del_foo, doc = 'Hello, I am foo!')
class D(C):def _get_foo(self):return self._foo * 2
def _set_foo(self, value):self._foo = value / 2
foo = property(fget = _get_foo, fset = _set_foo,fdel = C.foo.fdel, doc = C.foo.__doc__)

在Python2.6和3.0中:

class C(object):def __init__(self, foo, bar):self.foo = foo # read-write propertyself.bar = bar # simple attribute
@propertydef foo(self):'''Hello, I am foo!'''
return self._foo
@foo.setterdef foo(self, value):self._foo = value
@foo.deleterdef foo(self):del self._foo
class D(C):@C.foo.getterdef foo(self):return self._foo * 2
@foo.setterdef foo(self, value):self._foo = value / 2

要了解有关属性如何工作的更多信息,请参阅描述符

链接比较运算符:

>>> x = 5>>> 1 < x < 10True>>> 10 < x < 20False>>> x < 10 < x*10 < 100True>>> 10 > x <= 9True>>> 5 == x > 4True

如果你认为它在做1 < x,结果是True,然后比较True < 10,这也是True,那么不,这真的不是发生的事情(参见最后一个例子)。

一切都是动态的

“没有编译时”。Python中的一切都是运行时。模块是通过从上到下执行模块的源代码来“定义”的,就像脚本一样,结果的命名空间是模块的属性空间。同样,类是通过从上到下执行类主体来“定义”的,结果的命名空间是类的属性空间。类主体可以包含完全任意的代码——包括导入语句、循环和其他类语句。按照有时的要求“动态”创建一个类、函数甚至模块并不难;事实上,这是不可能避免的,因为一切都是“动态的”。

重新提出例外

# Python 2 syntaxtry:some_operation()except SomeError, e:if is_fatal(e):raisehandle_nonfatal(e)
# Python 3 syntaxtry:some_operation()except SomeError as e:if is_fatal(e):raisehandle_nonfatal(e)

在错误处理程序中没有参数的“提高”语句告诉Python重新提高异常原始的追踪记录完好无损,允许您说“哦,对不起,对不起,我不是故意抓住那个的,对不起,对不起。

如果你想打印、存储或摆弄原始的回溯,你可以使用sys.exc_info()来获取它,而像Python一样打印它是通过'traceback'模块完成的。

就地价值交换

>>> a = 10>>> b = 5>>> a, b(10, 5)
>>> a, b = b, a>>> a, b(5, 10)

赋值的右侧是创建新元组的表达式。赋值的左侧立即将该(未引用的)元组解包为名称ab

赋值后,新元组将不被引用并标记为垃圾回收机制,绑定到ab的值已被交换。

关于数据结构的Python教程部分所示,

请注意,多重赋值实际上只是元组打包和序列解包的组合。

描述符

它们是一大堆核心Python功能背后的魔力。

当你使用虚线访问来查找一个成员(例如,x. y)时,Python首先在实例字典中查找该成员。如果没有找到,它会在类字典中查找。如果它在类字典中找到它,并且该对象实现了描述符协议,而不仅仅是返回它,Python会执行它。描述符是实现__get____set____delete__方法的任何类。

以下是如何使用描述符实现自己的(只读)属性版本:

class Property(object):def __init__(self, fget):self.fget = fget
def __get__(self, obj, type):if obj is None:return selfreturn self.fget(obj)

你可以像使用内置属性()一样使用它:

class MyClass(object):@Propertydef foo(self):return "Foo!"

描述符在Python中用于实现属性、绑定方法、静态方法、类方法和槽等。了解它们很容易理解为什么很多以前看起来像Python的“怪癖”的东西都是这样的。

Raymond Hettinger有一个很好的教程,它比我更好地描述了它们。

Doctest:同时留档和单元测试。

从Python留档中提取的示例:

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 mathif 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 1e300raise OverflowError("n too large")result = 1factor = 2while factor <= n:result *= factorfactor += 1return result
def _test():import doctestdoctest.testmod()
if __name__ == "__main__":_test()

iter()可以接受可调用的参数

例如:

def seek_next_line(f):for c in iter(lambda: f.read(1),'\n'):pass

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

懒得初始化字典中的每个字段?没问题:

在Python>2.3中:

from collections import defaultdict

在Python<=2.3中:

def defaultdict(type_):class Dict(dict):def __getitem__(self, key):return self.setdefault(key, type_())return Dict()

在任何版本中:

d = defaultdict(list)for stuff in lots_of_stuff:d[stuff.name].append(stuff)

更新:

谢谢KenArnold。我重新实现了一个更复杂的default的版本。它的行为应该和标准库中的那个完全一样。

def defaultdict(default_factory, *args, **kw):
class defaultdict(dict):
def __missing__(self, key):if default_factory is None:raise KeyError(key)return self.setdefault(key, default_factory())
def __getitem__(self, key):try:return dict.__getitem__(self, key)except KeyError:return self.__missing__(key)
return defaultdict(*args, **kw)

Python解释器

>>>

也许不是鲜为人知,但肯定是我最喜欢的Python特性之一。

一流的功能

这不是一个真正的隐藏特性,但是函数是第一类对象的事实非常棒。您可以像任何其他变量一样传递它们。

>>> def jim(phrase):...   return 'Jim says, "%s".' % phrase>>> def say_something(person, phrase):...   print person(phrase)
>>> say_something(jim, 'hey guys')'Jim says, "hey guys".'

以完全动态的方式创建新类型

>>> NewType = type("NewType", (object,), {"x": "hello"})>>> n = NewType()>>> n.x"hello"

这与

>>> class NewType(object):>>>     x = "hello">>> n = NewType()>>> n.x"hello"

可能不是最有用的东西,但很高兴知道。

编辑:新类型的固定名称,应该是NewType,与class语句完全相同。

编辑:调整了标题以更准确地描述功能。

在列表推导中交错iffor

>>> [(x, y) for x in range(4) if x % 2 == 1 for y in range(4)][(1, 0), (1, 1), (1, 2), (1, 3), (3, 0), (3, 1), (3, 2), (3, 3)]

我从来没有意识到这一点,直到我学会了Haskell。

上下文管理器和“with”语句

PEP 343中引入的上下文管理器是一个对象,它充当一组语句的运行时上下文。

由于该功能使用了新的关键字,因此它是逐步引入的:它在Python 2.5中通过#0指令可用。Python 2.6及更高版本(包括Python 3)默认可用。

我经常使用“用”语句,因为我认为它是一个非常有用的结构,这里是一个快速演示:

from __future__ import with_statement
with open('foo.txt', 'w') as f:f.write('hello!')

这里在幕后发生的事情是,“用”语句调用文件对象上的特殊__enter____exit__方法。如果从with语句主体引发任何异常,异常详细信息也会传递给__exit__,从而允许异常处理在那里发生。

在这种特殊情况下,它为您做的是,它保证当执行超出with套件的范围时,文件将关闭,无论这种情况是否正常发生或是否抛出异常。

其他常见用例包括使用线程锁定和数据库事务。

一些内置收藏夹,map(),duce()和filter()。所有这些都非常快速和强大。

函数参数解包

您可以使用***将列表或字典解压缩为函数参数。

例如:

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)

非常有用的快捷方式,因为列表,元组和字典被广泛用作容器。

字典有一个get()方法

字典有一个'get()'方法。如果你做了d['key']而key不在那里,你会得到一个异常。如果你做了d.get('key'),如果'key'不在那里,你会得到无。你可以添加第二个参数来获取该项目而不是无,例如:d.get('key',0)。

它非常适合像加数字这样的事情:

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

如果您在函数中使用exec,变量查找规则会发生巨大变化。闭包不再可能,但Python允许在函数中使用任意标识符。这为您提供了一个“可修改的locals()”,并可用于星形导入标识符。不利的一面是,它会使每次查找都变慢,因为变量最终以字典而不是帧中的槽结束:

>>> def f():...  exec "a = 42"...  return a...>>> def g():...  a = 42...  return a...>>> import dis>>> dis.dis(f)2           0 LOAD_CONST               1 ('a = 42')3 LOAD_CONST               0 (None)6 DUP_TOP7 EXEC_STMT
3           8 LOAD_NAME                0 (a)11 RETURN_VALUE>>> dis.dis(g)2           0 LOAD_CONST               1 (42)3 STORE_FAST               0 (a)
3           6 LOAD_FAST                0 (a)9 RETURN_VALUE

从2.5开始,dicts有一个特殊的方法__missing__,用于缺少的项目:

>>> class MyDict(dict):...  def __missing__(self, key):...   self[key] = rv = []...   return rv...>>> m = MyDict()>>> m["foo"].append(1)>>> m["foo"].append(2)>>> dict(m){'foo': [1, 2]}

collections中还有一个名为defaultdict的字典子类,它的作用几乎相同,但调用一个没有参数的函数来处理不存在的项目:

>>> from collections import defaultdict>>> m = defaultdict(list)>>> m["foo"].append(1)>>> m["foo"].append(2)>>> dict(m){'foo': [1, 2]}

我建议在将它们传递给不需要此类子类的函数之前将此类dict转换为常规dict。许多代码使用d[a_key]并捕获KeyError来检查是否存在会向字典添加新项的项。

如果您在类上使用描述符,Python完全绕过该键的__dict__,这使得它成为存储此类值的好地方:

>>> class User(object):...  def _get_username(self):...   return self.__dict__['username']...  def _set_username(self, value):...   print 'username set'...   self.__dict__['username'] = value...  username = property(_get_username, _set_username)...  del _get_username, _set_username...>>> u = User()>>> u.username = "foo"username set>>> u.__dict__{'username': 'foo'}

这有助于保持dir()清洁。

如果您不喜欢使用空格来表示范围,您可以通过发出以下命令来使用C风格{}:

from __future__ import braces

__slots__是节省内存的好方法,但是很难得到对象的值。想象一下以下对象:

class Point(object):__slots__ = ('x', 'y')

现在该对象显然有两个属性。现在我们可以创建它的一个实例并以这种方式构建它的字典:

>>> p = Point()>>> p.x = 3>>> p.y = 5>>> dict((k, getattr(p, k)) for k in p.__slots__){'y': 5, 'x': 3}

然而,如果point被子类化并添加了新的插槽,这将不起作用。然而,Python自动实现__reduce_ex__来帮助copy模块。这可能被滥用以获取值的字典:

>>> p.__reduce_ex__(2)[2][1]{'y': 5, 'x': 3}

Python的高级切片操作有一个鲜为人知的语法元素,省略号:

>>> class C(object):...  def __getitem__(self, item):...   return item...>>> C()[1:2, ..., 3](slice(1, 2, None), Ellipsis, 3)

不幸的是,它几乎没有用,因为只有在涉及元组时才支持省略号。

内置方法或函数不实现描述符协议,这使得不可能做这样的事情:

>>> class C(object):...  id = id...>>> C().id()Traceback (most recent call last):File "<stdin>", line 1, in <module>TypeError: id() takes exactly one argument (0 given)

但是,您可以创建一个小型绑定描述符来实现这一点:

>>> from types import MethodType>>> class bind(object):...  def __init__(self, callable):...   self.callable = callable...  def __get__(self, obj, type=None):...   if obj is None:...    return self...   return MethodType(self.callable, obj, type)...>>> class C(object):...  id = bind(id)...>>> C().id()7414064

命名格式

%-格式化采用字典(也应用%i/%s等验证)。

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

由于locals()也是一个字典,你可以简单地将其作为一个字典传递,并从你的局部变量中获得%-substitions。

新样式格式

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

小心可变的默认参数

>>> 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]

元组解包:

>>> (a, (b, c), d) = [(1, 2), (3, 4), (5, 6)]>>> a(1, 2)>>> b3>>> c, d(4, (5, 6))

更模糊的是,你可以在函数参数中这样做(在Python 2. x中;Python 3. x不再允许这样做了):

>>> def addpoints((x1, y1), (x2, y2)):...     return (x1+x2, y1+y2)>>> addpoints((5, 0), (3, 5))(8, 5)

解压不需要在Python中

有人在博客上说Python没有unzip函数来使用zip()。unzip是直接计算的,因为:

>>> t1 = (0,1,2,3)>>> t2 = (7,6,5,4)>>> [t1,t2] == zip(*zip(t1,t2))True

经过反思,我宁愿有一个明确的unzip()。

为了添加更多的python模块(尤其是第三方模块),大多数人似乎使用PYTHONPATH环境变量,或者在他们的站点包目录中添加符号链接或目录。另一种方法是使用*. pth文件。这是官方python文档的解释:

"最方便的方法[修改python的搜索路径]是添加一个路径配置文件到目录已经在Python的路径上,通常是…/site-包/目录。路径配置文件扩展名为. pth,并且每个行必须包含一个路径将附加到sys.path.(因为新的路径被附加到sys.path,模块在添加目录不会覆盖标准模块。这意味着你不能用这个固定安装机构标准模块的版本。)"

异常否则子句:

try:put_4000000000_volts_through_it(parrot)except Voom:print "'E's pining!"else:print "This parrot is no more!"finally:end_sketch()

使用else子句比向try子句添加额外的代码要好,因为它避免了意外捕获由try…但语句保护的代码未引发的异常。

http://docs.python.org/tut/node10.html

for… else语法(参见http://docs.python.org/ref/for.html

for i in foo:if i == 0:breakelse:print("i was never 0")

通常情况下,“else”块将在for循环的末尾执行,除非调用出路。

上面的代码可以模拟如下:

found = Falsefor i in foo:if i == 0:found = Truebreakif not found:print("i was never 0")

很多人不知道“dir”函数。这是一个很好的方法,可以从解释器中找出对象可以做什么。例如,如果您想查看所有字符串方法的列表:

>>> dir("foo")['__add__', '__class__', '__contains__', (snipped a bunch), 'title','translate', 'upper', 'zfill']

然后,如果您想了解有关特定方法的更多信息,您可以在其上调用“帮助”。

>>> help("foo".upper)Help on built-in function upper:
upper(...)S.upper() -> string
Return a copy of the string S converted to uppercase.

访问字典元素作为属性(属性)。所以如果一个a1=AttrDICT()有键'name'->而不是a1['name']我们可以很容易地使用->访问a1的名称属性a1.name


class AttrDict(dict):
def __getattr__(self, name):if name in self:return self[name]raise AttributeError('%s not found' % name)
def __setattr__(self, name, value):self[name] = value
def __delattr__(self, name):del self[name]
person = AttrDict({'name': 'John Doe', 'age': 66})print person['name']print person.name
person.name = 'Frodo G'print person.name
del person.age
print person

Python排序函数对元组正确排序(即使用熟悉的字典顺序):

a = [(2, "b"), (1, "a"), (2, "a"), (3, "c")]print sorted(a)#[(1, 'a'), (2, 'a'), (2, 'b'), (3, 'c')]

如果您想在年龄之后对人员列表进行排序,然后是名称,则很有用。

有条件赋值

x = 3 if (y == 1) else 2

它的作用和听起来完全一样:“如果y为1,则将3分配给x,否则将2分配给x”。请注意,括号不是必需的,但我喜欢它们的易读性。如果你有更复杂的东西,你也可以链接它:

x = 3 if (y == 1) else 2 if (y == -1) else 1

虽然在某一点上,它走得有点远。

请注意,您可以在任何表达式中使用if… else。例如:

(func1 if y == 1 else func2)(arg1, arg2)

在这里,如果y为1且函数为2,则将调用函数1,否则。在这两种情况下,相应的函数都将使用参数ag 1和ag 2调用。

类似地,以下内容也是有效的:

x = (class1 if y == 1 else class2)(arg1, arg2)

其中类1和类2是两个类。

  • 下划线包含解释器显示的最新产出值(在交互式会话中):
>>> (a for a in xrange(10000))<generator object at 0x81a8fcc>>>> b = 'blah'>>> _<generator object at 0x81a8fcc>
  • 一个方便的Web浏览器控制器:
>>> import webbrowser>>> webbrowser.open_new_tab('http://www.stackoverflow.com')
  • 内置的超文本传输协议服务器。要提供当前目录中的文件:
python -m SimpleHTTPServer 8000
  • AtExit
>>> import atexit

__getattr__()

getattr是制作泛型类的一种非常好的方法,如果您正在编写API,这尤其有用。例如,在Python API中,getattr用于无缝地将方法调用传递给Web服务:

class FogBugz:...
def __getattr__(self, name):# Let's leave the private stuff to Pythonif name.startswith("__"):raise AttributeError("No such attribute '%s'" % name)
if not self.__handlerCache.has_key(name):def handler(**kwargs):return self.__makerequest(name, **kwargs)self.__handlerCache[name] = handlerreturn self.__handlerCache[name]...

当有人调用FogBugz.search(q='bug')时,他们实际上并没有调用search方法。相反,getattr通过创建一个包装makerequest方法的新函数来处理调用,该函数将适当的HTTP请求发送到Web API。任何错误都将由Web服务分派并传递回用户。

枚举

用enumerate包装可迭代对象,它将生成项目及其索引。

例如:

>>> a = ['a', 'b', 'c', 'd', 'e']>>> for index, item in enumerate(a): print index, item...0 a1 b2 c3 d4 e>>>

参考文献:

三元算子

>>> 'ham' if True else 'spam''ham'>>> 'ham' if False else 'spam''spam'

这是在2.5中添加的,在此之前,您可以使用:

>>> True and 'ham' or 'spam''ham'>>> False and 'ham' or 'spam''spam'

但是,如果要使用的值被认为是false,则存在差异:

>>> [] if True else 'spam'[]>>> True and [] or 'spam''spam'

您可以从一组长度为2的序列构建字典。当您有一个值列表和一个数组列表时非常方便。

>>> dict([ ('foo','bar'),('a',1),('b',2) ]){'a': 1, 'b': 2, 'foo': 'bar'}
>>> names = ['Bob', 'Marie', 'Alice']>>> ages = [23, 27, 36]>>> dict(zip(names, ages)){'Alice': 36, 'Bob': 23, 'Marie': 27}

元组解压循环、列表理解和生成器表达式:

>>> l=[(1,2),(3,4)]>>> [a+b for a,b in l ][3,7]

用于在字典中迭代(键,数据)对:

d = { 'x':'y', 'f':'e'}for name, value in d.items():  # one can also use iteritems()print "name:%s, value:%s" % (name,value)

印刷品:

name:x, value:yname:f, value:e

“解压”到函数参数

def foo(a, b, c):print a, b, c
bar = (3, 14, 15)foo(*bar)

执行时打印:

3 14 15

布尔上下文中的对象

空元组、列表、字典、字符串和许多其他对象在布尔上下文中等效于False(非空等效于True)。

empty_tuple = ()empty_list = []empty_dict = {}empty_string = ''empty_set = set()if empty_tuple or empty_list or empty_dict or empty_string or empty_set:print 'Never happens!'

这允许逻辑操作返回它的一个操作数而不是True/False,这在某些情况下很有用:

s = t or "Default value" # s will be assigned "Default value"# if t is false/empty/none

一切事物的第一类(“一切都是对象”),以及由此可能造成的混乱。

>>> x = 5>>> y = 10>>>>>> def sq(x):...   return x * x...>>> def plus(x):...   return x + x...>>> (sq,plus)[y>x](y)20

最后一行创建一个包含两个函数的元组,然后计算y>x(True)并将其用作元组的索引(通过将其转换为int,1),然后使用参数y调用该函数并显示结果。

对于进一步的滥用,如果你返回一个带有索引的对象(例如列表),你可以在末尾添加更多的方括号;如果内容是可调用的,更多的括号,依此类推。对于额外的变态,使用像这样的代码的结果作为另一个例子中的表达式(即用这段代码替换y>x):

(sq,plus)[y>x](y)[4](x)

这展示了Python的两个方面——“一切都是对象”的哲学发挥到了极致,以及不恰当或考虑不周的使用语言语法可能导致完全不可读、不可维护的意大利面条代码的方法。

分配和删除切片:

>>> a = range(10)>>> a[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> a[:5] = [42]>>> a[42, 5, 6, 7, 8, 9]>>> a[:1] = range(5)>>> a[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> del a[::2]>>> a[1, 3, 5, 7, 9]>>> a[::2] = a[::-2]>>> a[9, 3, 5, 7, 1]

说明:当分配给扩展切片(s[start:stop:step])时,分配的可迭代对象必须与切片具有相同的长度。

字典的构造函数接受关键字参数:

>>> dict(foo=1, bar=2){'foo': 1, 'bar': 2}

获取python正则表达式解析树来调试您的正则表达式。

正则表达式是python的一个很好的特性,但是调试它们可能很痛苦,而且很容易弄错正则表达式。

幸运的是,python可以通过将未记录的、实验性的、隐藏的标志re.DEBUG(实际上是128)传递给re.compile来打印正则表达式解析树。

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

一旦你理解了语法,你就可以发现你的错误。在那里,我们可以看到我忘记转义[/font]中的[]

当然,你可以将它与任何你想要的标志结合起来,比如注释的正则表达式:

>>> 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)

内置bas64、zlib和rot13编解码器

字符串有encodedecode方法。通常这用于将str转换为unicode,反之亦然,例如u = s.encode('utf8')。但是还有一些其他方便的内置编解码器。使用zlib(和bz2)的压缩和解压缩无需显式导入即可使用:

>>> s = 'a' * 100>>> s.encode('zlib')'x\x9cKL\xa4=\x00\x00zG%\xe5'

同样,您可以编码和解码bas64:

>>> 'Hello world'.encode('base64')'SGVsbG8gd29ybGQ=\n'>>> 'SGVsbG8gd29ybGQ=\n'.decode('base64')'Hello world'

而且,当然,你可以rot 13:

>>> 'Secret message'.encode('rot13')'Frperg zrffntr'

显然,反重力模块。xkcd#353

发电机

我认为,很多刚开始学习Python的开发人员忽略了生成器,却没有真正理解它们的用途或了解它们的强大功能。直到我阅读了David M. Beazley关于生成器的PyCon演讲(可用这里),我才意识到它们是多么有用(真的很重要)。那个演讲阐明了对我来说是一种全新的编程方式,我把它推荐给任何对生成器没有深刻理解的人。

交互式解释器选项卡完成

try:import readlineexcept ImportError:print "Unable to load readline module."else:import rlcompleterreadline.parse_and_bind("tab: complete")

>>> 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()

您还必须设置PYTHONSTARTUP环境变量。

Python已经开始了

…它由外部纯Python模块实现:)

from goto import goto, labelfor i in range(1, 10):for j in range(1, 20):for k in range(1, 30):print i, j, kif k == 3:goto .end # breaking out from a deeply nested looplabel .endprint "Finished"

利用python的动态特性来创建应用程序以python语法配置文件。例如,如果您有以下内容在配置文件中:

{"name1": "value1","name2": "value2"}

然后你可以简单地阅读它:

config = eval(open("filename").read())

嵌套函数参数重新绑定

def create_printers(n):for i in xrange(n):def printer(i=i): # Doesn't work without the i=iprint iyield printer

python的一个小错误。将字符串列表连接在一起的正常快速方法是,

''.join(list_of_strings)

私有方法和数据隐藏(封装)

在Python中有一个常见的习语,通过赋予方法和其他类成员以下划线开头的名称来表示它们不打算成为类外部API的一部分。这很方便,在实践中效果很好,但它给人一种错误的印象,即Python不支持私有代码和/或数据的真正封装。事实上,Python会自动给你词汇闭包,这使得在情况真正需要时以更加防弹的方式封装数据变得非常容易。这是一个利用这种技术的类的做作示例:

class MyClass(object):def __init__(self):
privateData = {}
self.publicData = 123
def privateMethod(k):print privateData[k] + self.publicData
def privilegedMethod():privateData['foo'] = "hello "privateMethod('foo')
self.privilegedMethod = privilegedMethod
def publicMethod(self):print self.publicData

下面是它使用的一个做作的例子:

>>> obj = MyClass()>>> obj.publicMethod()123>>> obj.publicData = 'World'>>> obj.publicMethod()World>>> obj.privilegedMethod()hello World>>> obj.privateMethod()Traceback (most recent call last):File "<stdin>", line 1, in <module>AttributeError: 'MyClass' object has no attribute 'privateMethod'>>> obj.privateDataTraceback (most recent call last):File "<stdin>", line 1, in <module>AttributeError: 'MyClass' object has no attribute 'privateData'

关键是privateMethodprivateData根本不是obj的真正属性,所以它们不能从外部访问,也不会出现在dir()或类似的地方。它们是构造函数中的局部变量,在__init__之外完全无法访问。然而,由于闭包的魔力,它们实际上是每个实例的变量,与它们关联的对象具有相同的生命周期,即使除了(在本例中)通过调用privilegedMethod之外没有办法从外部访问它们。这种非常严格的封装通常是矫枉过正的,但有时它真的可以非常方便地保持API或命名空间的整洁。

在Python 2. x中,拥有可变私有状态的唯一方法是使用可变对象(例如本示例中的字典)。许多人已经评论过这有多烦人。Python 3. x将通过引入PEP 3104中描述的nonlocal关键字来消除此限制。

使用关键字参数作为赋值

有时人们想根据一个或多个参数构建一系列函数。然而,这可能很容易导致闭包都引用相同的对象和值:

funcs = []for k in range(10):funcs.append( lambda: k)
>>> funcs[0]()9>>> funcs[7]()9

可以通过仅根据其参数将lambda表达式转换为函数来避免这种行为。关键字参数存储绑定到它的当前值。函数调用不必更改:

funcs = []for k in range(10):funcs.append( lambda k = k: k)
>>> funcs[0]()0>>> funcs[7]()7

对象实例的方法替换

您可以替换已经创建的对象实例的方法。它允许您创建具有不同(特殊)功能的对象实例:

>>> class C(object):...     def fun(self):...         print "C.a", self...>>> inst = C()>>> inst.fun()  # C.a method is executedC.a <__main__.C object at 0x00AE74D0>>>> instancemethod = type(C.fun)>>>>>> def fun2(self):...     print "fun2", self...>>> inst.fun = instancemethod(fun2, inst, C)  # Now we are replace C.a by fun2>>> inst.fun()  # ... and fun2 is executedfun2 <__main__.C object at 0x00AE74D0>

我们可以在inst实例中将C.a替换为fun2()self没有改变)。

或者我们可以使用new模块,但它从Python 2.6开始贬值:

>>> def fun3(self):...     print "fun3", self...>>> import new>>> inst.fun = new.instancemethod(fun3, inst, C)>>> inst.fun()fun3 <__main__.C object at 0x00AE74D0>

节点:这个解决方案不应该被用作继承机制的一般替换!但在一些特定情况下(调试、模拟)可能会非常方便。

警告:此解决方案不适用于内置类型和使用插槽的新样式类。

在构建时引用列表理解…

您可以引用由符号“_[1]”构建的列表推导。例如,以下函数通过引用其列表推导来唯一化元素列表而不更改它们的顺序。

def unique(my_list):return [x for x in my_list if x not in locals()['_[1]']]

set/Frozenset

可能一个容易被忽视的Python内置程序是“set/Frozenset”。

当你有这样的列表时很有用,[1,2,1,1,2,3,4]并且只想要这样的唯一项[1,2,3,4]。

使用set()这正是你得到的:

>>> x = [1,2,1,1,2,3,4]>>>>>> set(x)set([1, 2, 3, 4])>>>>>> for i in set(x):...     print i...1234

当然,要获得列表中唯一的数量:

>>> len(set([1,2,1,1,2,3,4]))4

您还可以使用set(). issubset()查找列表是否是另一个列表的子集:

>>> set([1,2,3,4]).issubset([0,1,2,3,4,5])True

从Python 2.7和3.0开始,您可以使用花括号创建一个集合:

myset = {1,2,3,4}

以及集合理解:

{x for x in stuff}

更多详情:http://docs.python.org/library/stdtypes.html#set

功能支持。

特别是生成器和生成器表达式。

Ruby再次成为主流,但Python也可以做到这一点。不像Ruby那样在库中无处不在,这太糟糕了,但我更喜欢语法,它更简单。

因为它们不是无处不在的,所以我没有看到很多关于它们为什么有用的例子,但是它们让我能够编写更干净,更高效的代码。

而调试复杂的数据结构pprint模块派上用场。

引用文档…

>>> import pprint>>> stuff = sys.path[:]>>> stuff.insert(0, stuff)>>> pprint.pprint(stuff)[<Recursion on list with id=869440>,'','/usr/local/lib/python1.5','/usr/local/lib/python1.5/test','/usr/local/lib/python1.5/sunos5','/usr/local/lib/python1.5/sharedmodules','/usr/local/lib/python1.5/tkinter']
>>> from functools import partial>>> bound_func = partial(range, 0, 10)>>> bound_func()[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> bound_func(2)[0, 2, 4, 6, 8]

不是真正的隐藏功能,但部分对于函数的后期评估非常有用。

您可以根据需要在初始调用中绑定尽可能多或尽可能少的参数,并在稍后使用任何剩余参数调用它(在本例中,我已将开始/结束参数绑定到范围,但第二次使用步骤参数调用它)

留档

is_ok() and "Yes" or "No"

dict.get()有一个默认值为无,从而避免了键错误:

In [1]: test = { 1 : 'a' }
In [2]: test[2]---------------------------------------------------------------------------<type 'exceptions.KeyError'>              Traceback (most recent call last)
&lt;ipython console&gt; in <module>()
<type 'exceptions.KeyError'>: 2
In [3]: test.get( 2 )
In [4]: test.get( 1 )Out[4]: 'a'
In [5]: test.get( 2 ) == NoneOut[5]: True

甚至指定这个“在现场”:

In [6]: test.get( 2, 'Some' ) == 'Some'Out[6]: True

你可以使用setdefault()设置一个值,如果它不存在则返回:

>>> a = {}>>> b = a.setdefault('foo', 'bar')>>> a{'foo': 'bar'}>>> b'bar

您可以轻松地使用zip转置数组。

a = [(1,2), (3,4), (5,6)]zip(*a)# [(1, 3, 5), (2, 4, 6)]

负轮

round()函数将浮点数舍入到十进制数字的给定精度,但精度可以为负:

>>> str(round(1234.5678, -2))'1200.0'>>> str(round(1234.5678, 2))'1234.57'

备注:round()总是返回一个浮点数,上面的例子中使用了str(),因为浮点数不精确,在2. x下,第二个例子可以打印为1234.5700000000001。另见#3模块。

解释器中的解释器

标准库的代码模块允许您在程序中包含自己的读取-评估-打印循环,或者运行整个嵌套解释器。例如。(从这里复制了我的示例)

$ pythonPython 2.5.1 (r251:54863, Jan 17 2008, 19:35:17)[GCC 4.0.1 (Apple Inc. build 5465)] on darwinType "help", "copyright", "credits" or "license" for more information.>>> shared_var = "Set in main console">>> import code>>> ic = code.InteractiveConsole({ 'shared_var': shared_var })>>> try:...     ic.interact("My custom console banner!")... except SystemExit, e:...     print "Got SystemExit!"...My custom console banner!>>> shared_var'Set in main console'>>> shared_var = "Set in sub-console">>> import sys>>> sys.exit()Got SystemExit!>>> shared_var'Set in main console'

这对于想要接受来自用户的脚本输入或实时查询VM状态的情况非常有用。

TurboGears通过拥有一个WebConsole来使用它,您可以从中查询实时Web应用程序的状态,从而产生了巨大的效果。

set内置的运算符重载:

>>> a = set([1,2,3,4])>>> b = set([3,4,5,6])>>> a | b # Union{1, 2, 3, 4, 5, 6}>>> a & b # Intersection{3, 4}>>> a < b # SubsetFalse>>> a - b # Difference{1, 2}>>> a ^ b # Symmetric Difference{1, 2, 5, 6}

来自标准库参考的更多详细信息:集合类型

你可以用元类覆盖类的mro

>>> class A(object):...     def a_method(self):...         print("A")...>>> class B(object):...     def b_method(self):...         print("B")...>>> class MROMagicMeta(type):...     def mro(cls):...         return (cls, B, object)...>>> class C(A, metaclass=MROMagicMeta):...     def c_method(self):...         print("C")...>>> cls = C()>>> cls.c_method()C>>> cls.a_method()Traceback (most recent call last):File "<stdin>", line 1, in <module>AttributeError: 'C' object has no attribute 'a_method'>>> cls.b_method()B>>> type(cls).__bases__(<class '__main__.A'>,)>>> type(cls).__mro__(<class '__main__.C'>, <class '__main__.B'>, <class 'object'>)

这可能是隐藏的一个很好的理由:)

reversed()内置。在许多情况下,它使迭代更清晰。

快速示例:

for i in reversed([1, 2, 3]):print(i)

生产:

321

但是,reversed()也适用于任意迭代器,例如文件中的行或生成器表达式。

Python的禅

>>> import thisThe 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.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!

pdb-Python调试器

作为一名程序员,您需要进行认真的程序开发的首要任务之一是调试器。Python有一个内置的模块,称为pdb(自然是“Python DeBugger”!)。

http://docs.python.org/library/pdb.html

小整数(-5…256)的对象从未创建过两次:

>>> a1 = -5; b1 = 256>>> a2 = -5; b2 = 256>>> id(a1) == id(a2), id(b1) == id(b2)(True, True)>>>>>> c1 = -6; d1 = 257>>> c2 = -6; d2 = 257>>> id(c1) == id(c2), id(d1) == id(d2)(False, False)>>>

编辑:列表对象从未被销毁(仅限于列表中的对象)。Python有一个数组,它在其中保存了多达80个空列表。当你销毁列表对象时,python会将其放入该数组,当你创建新列表时,python会从此数组中获取最后一个计算列表:

>>> a = [1,2,3]; a_id = id(a)>>> b = [1,2,3]; b_id = id(b)>>> del a; del b>>> c = [1,2,3]; id(c) == b_idTrue>>> d = [1,2,3]; id(d) == a_idTrue>>>

创建具有相关数据的两个序列的字典

In [15]: t1 = (1, 2, 3)
In [16]: t2 = (4, 5, 6)
In [17]: dict (zip(t1,t2))Out[17]: {1: 4, 2: 5, 3: 6}

使用and和or模拟三元算子。

python中的and和或运算符返回对象本身而不是布尔值。因此:

In [18]: a = True
In [19]: a and 3 or 4Out[19]: 3
In [20]: a = False
In [21]: a and 3 or 4Out[21]: 4

然而,Py 2.5似乎添加了一个显式的三级运算符

    In [22]: a = 5 if True else '6'
In [23]: aOut[23]: 5

如果您确定true子句的计算结果不会为False,那么这就有效了。

>>> def foo():...     print "foo"...     return 0...>>> def bar():...     print "bar"...     return 1...>>> 1 and foo() or bar()foobar1

为了让它正确,你必须再多一点:

>>> (1 and [foo()] or [bar()])[0]foo0

但是,这并不漂亮。如果您的python版本支持它,请使用条件运算符。

>>> foo() if True or bar()foo0

检查模块也是一个很酷的功能。

标准Python中的spam模块

它用于测试目的。

我从#0教程中选择了它。你自己试试:

>>> import __hello__Hello world...>>> type(__hello__)<type 'module'>>>> from __phello__ import spamHello world...Hello world...>>> type(spam)<type 'module'>>>> help(spam)Help on module __phello__.spam in __phello__:
NAME__phello__.spam
FILEc:\python26\<frozen>

内存管理

Python动态分配内存并使用垃圾回收机制来恢复未使用的空间。一旦对象超出范围,并且没有其他变量引用它,它就会被恢复。我不必担心缓冲区溢出和缓慢增长的服务器进程。内存管理也是其他动态语言的一个特性,但Python就是做得很好。

当然,我们必须注意循环引用和保留对不再需要的对象的引用,但是弱引用在这里很有帮助。

re可以调用函数!

每次匹配正则表达式时都可以调用函数这一事实非常方便。在这里,我有一个用“嗨”替换每个“你好”的示例,用“弗雷德”替换“那里”,等等。

import re
def Main(haystack):# List of from replacements, can be a regexfinds = ('Hello', 'there', 'Bob')replaces = ('Hi,', 'Fred,', 'how are you?')
def ReplaceFunction(matchobj):for found, rep in zip(matchobj.groups(), replaces):if found != None:return rep
# log errorreturn matchobj.group(0)
named_groups = [ '(%s)' % find for find in finds ]ret = re.sub('|'.join(named_groups), ReplaceFunction, haystack)print ret
if __name__ == '__main__':str = 'Hello there Bob'Main(str)# Prints 'Hi, Fred, how are you?'

我个人喜欢3不同的报价

str = "I'm a string 'but still I can use quotes' inside myself!"str = """ For some messy multi line strings.Such as<html><head> ... </head>"""

也很酷:不必转义正则表达式,通过使用原始字符串避免可怕的反斜杠沙拉:

str2 = r"\n"print str2>> \n

一个字:IPython

标签反省,漂亮印刷,%debug,历史管理,pylab,……值得花时间好好学习。

重新加载模块可以实现“实时编码”风格。但是类实例不会更新。这是原因以及如何绕过它。记住,一切,是的,一切是一个对象。

>>> from a_package import a_module>>> cls = a_module.SomeClass>>> obj = cls()>>> obj.method()(old method output)

现在更改a_module.py中的方法并想要更新对象。

>>> reload(a_module)>>> a_module.SomeClass is clsFalse # Because it just got freshly created by reload.>>> obj.method()(old method output)

这里有一种更新它的方法(但考虑用剪刀运行):

>>> obj.__class__ is clsTrue # it's the old class object>>> obj.__class__ = a_module.SomeClass # pick up the new class>>> obj.method()(new method output)

这是“剪刀式运行”,因为对象的内部状态可能与新类期望的不同。这适用于非常简单的情况,但除此之外,pickle是你的朋友。不过,理解为什么这有效仍然很有帮助。

不是很隐藏,但函数有属性:

def doNothing():pass
doNothing.monkeys = 4print doNothing.monkeys4

你可以用类装饰函数——用类实例替换函数:

class countCalls(object):""" decorator replaces a function with a "countCalls" instancewhich behaves like the original function, but keeps track of calls
>>> @countCalls... def doNothing():...     pass>>> doNothing()>>> doNothing()>>> print doNothing.timesCalled2"""def __init__ (self, functionToTrack):self.functionToTrack = functionToTrackself.timesCalled = 0def __call__ (self, *args, **kwargs):self.timesCalled += 1return self.functionToTrack(*args, **kwargs)

通过少量的工作,线程模块变得非常容易使用。此装饰器更改函数以使其在自己的线程中运行,返回占位符类实例而不是其常规结果。你可以通过检查placeolder.result来探测答案,也可以通过调用placeholder.awaitResult()来等待它

def threadify(function):"""exceptionally simple threading decorator. Just:>>> @threadify... def longOperation(result):...     time.sleep(3)...     return result>>> A= longOperation("A has finished")>>> B= longOperation("B has finished")
A doesn't have a result yet:>>> print A.resultNone
until we wait for it:>>> print A.awaitResult()A has finished
we could also wait manually - half a second more should be enough for B:>>> time.sleep(0.5); print B.resultB has finished"""class thr (threading.Thread,object):def __init__(self, *args, **kwargs):threading.Thread.__init__ ( self )self.args, self.kwargs = args, kwargsself.result = Noneself.start()def awaitResult(self):self.join()return self.resultdef run(self):self.result=function(*self.args, **self.kwargs)return thr

ROT13是源代码的有效编码,当您在代码文件顶部使用正确的编码声明时:

#!/usr/bin/env python# -*- coding: rot13 -*-
cevag "Uryyb fgnpxbiresybj!".rapbqr("rot13")

如果您在应用程序中重命名了一个类,您正在通过Pickle加载用户保存的文件,并且其中一个重命名的类存储在用户的旧保存中,您将无法加载该腌制文件。

但是,只需添加对类定义的引用,一切都很好:

例如,在:

class Bleh:pass

现在,

class Blah:pass

因此,您的用户的腌制保存文件包含对Bleh的引用,由于重命名而不存在。修复?

Bleh = Blah

简单!

一切都是对象,因此是可扩展的。我可以将成员变量作为元数据添加到我定义的函数中:

>>> def addInts(x,y):...    return x + y>>> addInts.params = ['integer','integer']>>> addInts.returnType = 'integer'

这对于编写动态单元测试非常有用,例如。

getattr内置函数:

>>> class C():def getMontys(self):self.montys = ['Cleese','Palin','Idle','Gilliam','Jones','Chapman']return self.montys

>>> c = C()>>> getattr(c,'getMontys')()['Cleese', 'Palin', 'Idle', 'Gilliam', 'Jones', 'Chapman']>>>

如果您想根据上下文分派函数,则很有用。请参阅深入Python(这里)中的示例

简单的方法来测试一个键是否在一个字典中:

>>> 'key' in { 'key' : 1 }True
>>> d = dict(key=1, key2=2)>>> if 'key' in d:...     print 'Yup'...Yup

类作为第一类对象(通过动态类定义显示)

也请注意闭包的使用。如果这个特定的例子看起来像是解决问题的“正确”方法,请仔细重新考虑……几次:)

def makeMeANewClass(parent, value):class IAmAnObjectToo(parent):def theValue(self):return valuereturn IAmAnObjectToo
Klass = makeMeANewClass(str, "fred")o = Klass()print isinstance(o, str)  # => Trueprint o.theValue()        # => fred

暴露可变缓冲区

在Python(2.5/2.6)中使用Python缓冲协议公开可变的面向字节的缓冲区

(对不起,这里没有代码。需要使用低级C API或现有的适配器模块)。

在子类中扩展属性(定义为描述符)

有时在子类中扩展(修改)描述符“返回”的值很有用。它可以很容易地使用super()完成:

class A(object):@propertydef prop(self):return {'a': 1}
class B(A):@propertydef prop(self):return dict(super(B, self).prop, b=2)

将其存储在test.py中并运行python -i test.py另一个隐藏功能:#2选项执行脚本并允许您在交互模式下继续):

>>> B().prop{'a': 1, 'b': 2}

pythonic成语x = ... if ... else ...远远优于x = ... and ... or ...,原因如下:

虽然声明

x = 3 if (y == 1) else 2

相当于

x = y == 1 and 3 or 2

如果你使用x = ... and ... or ...这个成语,有一天你可能会被这个棘手的情况所困扰:

x = 0 if True else 1    # sets x equal to 0

因此不等于

x = True and 0 or 1   # sets x equal to 1

更多关于正确的方法,Python的隐藏特性.

Python可以理解任何类型的Unicode数字,不仅仅是ASCII类型:

>>> s = u'10585'>>> su'\uff11\uff10\uff15\uff18\uff15'>>> print s10585>>> int(s)10585>>> float(s)10585.0

关于Nick Johnson对属性类的实现(当然,这只是描述符的演示,而不是内置描述符的替代品),我将包含一个引发At的setter:

class Property(object):def __init__(self, fget):self.fget = fget
def __get__(self, obj, type):if obj is None:return selfreturn self.fget(obj)
def __set__(self, obj, value):raise AttributeError, 'Read-only attribute'

包含setter使其成为数据描述符,而不是方法/非数据描述符。数据描述符优先于实例字典。现在实例不能将不同的对象分配给属性名称,并且尝试分配给属性将引发属性错误。

解包语法在最近的版本中进行了升级,如示例所示。

>>> a, *b = range(5)>>> a, b(0, [1, 2, 3, 4])>>> *a, b = range(5)>>> a, b([0, 1, 2, 3], 4)>>> a, *b, c = range(5)>>> a, b, c(0, [1, 2, 3], 4)

操纵递归极限

使用sys.getrecursionlimit()和sys.setrecursionlimit()获取或设置递归的最大深度。

我们可以限制它以防止由无限递归引起的堆栈溢出。

乘以一个布尔值

我在Web开发中经常做的一件事是可选地打印超文本标记语言参数。我们都在其他语言中看到过这样的代码:

class='<% isSelected ? "selected" : "" %>'

在Python中,你可以乘以一个布尔值,它完全符合你的期望:

class='<% "selected" * isSelected %>'

这是因为乘法将布尔值强制转换为整数(0表示False,1表示True),并且在python中将字符串乘以int重复将字符串N次。

Mod可以正确处理负数

-1%5是4,应该是,而不是像JavaScript等其他语言中的-1。这使得Python中的“环绕窗口”更干净,你只需这样做:

index = (index + increment) % WINDOW_SIZE

您可以按需构造函数kwargs:

kwargs = {}kwargs[str("%s__icontains" % field)] = some_valuesome_function(**kwargs)

str()调用在某种程度上是需要的,因为python抱怨它没有字符串。不知道为什么;)我在Django对象模型中使用这个动态过滤器:

result = model_class.objects.filter(**kwargs)

猜测整数基数

>>> int('10', 0)10>>> int('0x10', 0)16>>> int('010', 0)  # does not work on Python 3.x8>>> int('0o10', 0)  # Python >=2.6 and Python 3.x8>>> int('0b10', 0)  # Python >=2.6 and Python 3.x2

迭代工具

这个模块经常被忽略。以下示例使用itertools.chain()将列表展平:

>>> from itertools import *>>> l = [[1, 2], [3, 4]]>>> list(chain(*l))[1, 2, 3, 4]

有关更多应用程序,请参阅http://docs.python.org/library/itertools.html#recipes

猴子修补对象

Python中的每个对象都有一个__dict__成员,用于存储对象的属性。所以,你可以这样做:

class Foo(object):def __init__(self, arg1, arg2, **kwargs):#do stuff with arg1 and arg2self.__dict__.update(kwargs)
f = Foo('arg1', 'arg2', bar=20, baz=10)#now f is a Foo object with two extra attributes

这可被利用来向对象任意添加属性和函数。这也可以被利用来创建快速脏struct类型。

class struct(object):def __init__(**kwargs):self.__dict__.update(kwargs)
s = struct(foo=10, bar=11, baz="i'm a string!')

创建枚举

在Python中,您可以这样做来快速创建枚举:

>>> FOO, BAR, BAZ = range(3)>>> FOO0

但是“枚举”不必有整数值。你甚至可以这样做:

class Colors(object):RED, GREEN, BLUE, YELLOW = (255,0,0), (0,255,0), (0,0,255), (0,255,255)
#now Colors.RED is a 3-tuple that returns the 24-bit 8bpp RGB#value for saturated red

操纵sys.modules

您可以直接操作模块缓存,根据需要使模块可用或不可用:

>>> import sys>>> import hamTraceback (most recent call last):File "<stdin>", line 1, in <module>ImportError: No module named ham
# Make the 'ham' module available -- as a non-module object even!>>> sys.modules['ham'] = 'ham, eggs, saussages and spam.'>>> import ham>>> ham'ham, eggs, saussages and spam.'
# Now remove it again.>>> sys.modules['ham'] = None>>> import hamTraceback (most recent call last):File "<stdin>", line 1, in <module>ImportError: No module named ham

这甚至适用于可用的模块,并且在某种程度上适用于已经进口的模块:

>>> import os# Stop future imports of 'os'.>>> sys.modules['os'] = None>>> import osTraceback (most recent call last):File "<stdin>", line 1, in <module>ImportError: No module named os# Our old imported module is still available.>>> os<module 'os' from '/usr/lib/python2.5/os.pyc'>

如最后一行所示,更改sys.modules只影响未来的import语句,而不影响过去的语句,因此如果您想影响其他模块,请务必进行这些更改之前,让它们有机会尝试导入模块-因此,通常情况下,在导入它们之前。Nonesys.modules中的一个特殊值,用于负缓存(表示第一次未找到模块,因此无需再次查找)。任何其他值都将是import操作的结果-即使它不是模块对象。您可以使用它来将模块替换为行为与您想要的完全相同的对象。从sys.modules完全删除条目会导致下一个import对模块进行正常搜索,即使它之前已经导入。

Python中没有秘密;)

将元组传递给内置函数

许多Python函数接受元组,看起来也不是。例如,你想测试你的变量是否是一个数字,你可以这样做:

if isinstance (number, float) or isinstance (number, int):print "yaay"

但是如果你给我们传递元组,这看起来更清晰:

if isinstance (number, (float, int)):print "yaay"

您可以将多个变量分配给同一个值

>>> foo = bar = baz = 1>>> foo, bar, baz(1, 1, 1)

有用的初始化几个变量为无,在一个紧凑的方式。

threading.enumerate()提供对系统中所有Thread对象的访问,而sys._current_frames()返回系统中所有线程的当前堆栈帧,因此将这两者结合起来,您将获得Java样式的堆栈转储:

def dumpstacks(signal, frame):id2name = dict([(th.ident, th.name) for th in threading.enumerate()])code = []for threadId, stack in sys._current_frames().items():code.append("\n# Thread: %s(%d)" % (id2name[threadId], threadId))for filename, lineno, name, line in traceback.extract_stack(stack):code.append('File: "%s", line %d, in %s' % (filename, lineno, name))if line:code.append("  %s" % (line.strip()))print "\n".join(code)
import signalsignal.signal(signal.SIGQUIT, dumpstacks)

在多线程python程序开始时这样做,您可以通过发送SIGQUIT随时访问线程的当前状态。您也可以选择signal.SIGUSR1或signal.SIGUSR2。

参见

牙套

def g():print 'hi!'
def f(): (g())
>>> f()hi!

绝密属性

>>> class A(object): pass>>> a = A()>>> setattr(a, "can't touch this", 123)>>> dir(a)['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', "can't touch this"]>>> a.can't touch this # duhFile "<stdin>", line 1a.can't touch this^SyntaxError: EOL while scanning string literal>>> getattr(a, "can't touch this")123>>> setattr(a, "__class__.__name__", ":O")>>> a.__class__.__name__'A'>>> getattr(a, "__class__.__name__")':O'

字典中无限递归的不错处理:

>>> a = {}>>> b = {}>>> a['b'] = b>>> b['a'] = a>>> print a{'b': {'a': {...}}}

对迭代器的多次引用

您可以使用列表乘法创建对同一迭代器的多个引用:

>>> i = (1,2,3,4,5,6,7,8,9,10) # or any iterable object>>> iterators = [iter(i)] * 2>>> iterators[0].next()1>>> iterators[1].next()2>>> iterators[0].next()3

这可用于将可迭代对象分组为块,例如,在这个示例中,来自#0留档

def grouper(n, iterable, fillvalue=None):"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"args = [iter(iterable)] * nreturn izip_longest(fillvalue=fillvalue, *args)

您可以通过查看任何对象的__module__属性来询问它来自哪个模块。这很有用,例如,如果您正在尝试使用命令行并导入了很多东西。

同样,您可以通过查看模块的__file__属性来询问它来自哪里。

使用负步长反转可迭代对象

>>> s = "Hello World">>> s[::-1]'dlroW olleH'>>> a = (1,2,3,4,5,6)>>> a[::-1](6, 5, 4, 3, 2, 1)>>> a = [5,4,3,2,1]>>> a[::-1][1, 2, 3, 4, 5]

使用交互式shell时,“_”包含最后打印项目的值:

>>> range(10)[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> _[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>>

切片和可变性

复制列表

>>> x = [1,2,3]>>> y = x[:]>>> y.pop()3>>> y[1, 2]>>> x[1, 2, 3]

替换列表

>>> x = [1,2,3]>>> y = x>>> y[:] = [4,5,6]>>> x[4, 5, 6]

将解压与打印功能结合使用:

# in 2.6 <= python < 3.0, 3.0 + the print function is nativefrom __future__ import print_function
mylist = ['foo', 'bar', 'some other value', 1,2,3,4]print(*mylist)

正如许多人所要求的那样,这个答案已经被移入了问题本身。

从python 3.1(2.7)开始,支持字典和集合理解:

{ a:a for a in range(10) }{ a for a in range(10) }

如果在序列的最后一个元素之后找到逗号,Python 2. x会忽略:

>>> a_tuple_for_instance = (0,1,2,3,)>>> another_tuple = (0,1,2,3)>>> a_tuple_for_instance == another_tupleTrue

尾随逗号导致单个括号元素被视为序列:

>>> a_tuple_with_one_element = (8,)
** Using sets to reference contents in sets of frozensets**

您可能知道,集合是可变的,因此不可散列,因此如果您想创建一组集合(或使用集合作为字典键),则有必要使用Frozenset:

>>> fabc = frozenset('abc')>>> fxyz = frozenset('xyz')>>> mset = set((fabc, fxyz))>>> mset{frozenset({'a', 'c', 'b'}), frozenset({'y', 'x', 'z'})}

但是,可以仅使用普通集合测试成员资格并删除/丢弃成员:

>>> abc = set('abc')>>> abc in msetTrue>>> mset.remove(abc)>>> mset{frozenset({'y', 'x', 'z'})}

引用Python标准库文档:

注意,__contains__()remove()discard()elem参数方法可以是一个集合。为了支持搜索等效的Frozenset,elem集合在搜索过程中暂时突变,然后恢复。在搜索时,不应读取或修改elem集合,因为它不有意义的价值。

不幸的是,也许令人惊讶的是,字典并非如此:

>>> mdict = {fabc:1, fxyz:2}>>> fabc in mdictTrue>>> abc in mdictTraceback (most recent call last):File "<interactive input>", line 1, in <module>TypeError: unhashable type: 'set'

Python中的#0实用函数可以非常方便地测试返回的多行字符串是否等于预期输出,而不会破坏单元测试的缩进:

import unittest, textwrap
class XMLTests(unittest.TestCase):def test_returned_xml_value(self):returned_xml = call_to_function_that_returns_xml()expected_value = textwrap.dedent("""\<?xml version="1.0" encoding="utf-8"?><root_node><my_node>my_content</my_node></root_node>""")
self.assertEqual(expected_value, returned_xml)

作为左值的切片。此Eratosthenes筛选产生一个包含素数或0的列表。元素在循环中通过切片赋值而为0。

def eras(n):last = n + 1sieve = [0,0] + list(range(2, last))sqn = int(round(n ** 0.5))it = (i for i in xrange(2, sqn + 1) if sieve[i])for i in it:sieve[i*i:last:i] = [0] * (n//i - i + 1)return filter(None, sieve)

为了工作,左边的切片必须在右边分配一个相同长度的列表。

零参数和可变参数lambda

Lambda函数通常用于将一个值快速转换为另一个值,但它们也可用于将值包装在函数中:

>>> f = lambda: 'foo'>>> f()'foo'

他们也可以接受通常的*args**kwargs语法:

>>> g = lambda *args, **kwargs: args[0], kwargs['thing']>>> g(1, 2, 3, thing='stuff')(1, 'stuff')

多行字符串

一种方法是使用反斜杠:

>>> sql = "select * from some_table \where id > 10">>> print sqlselect * from some_table where id > 10

另一个是使用三重引用:

>>> sql = """select * from some_tablewhere id > 10""">>> print sqlselect * from some_table where id > 10

问题是它们没有缩进(在你的代码中看起来很差)。如果你尝试缩进,它只会打印你放的空格。

我最近发现的第三种解决方案是将字符串分成行并用括号括起来:

>>> sql = ("select * from some_table " # <-- no comma, whitespace at end"where id > 10 ""order by name")>>> print sqlselect * from some_table where id > 10 order by name

注意行之间没有逗号(这不是元组),并且您必须考虑字符串需要的任何尾随/前导空格。顺便说一句,所有这些都适用于占位符(例如"my name is %s" % name)。

pow()也可以有效地计算(x**y)%z。

内置pow()函数有一个鲜为人知的第三个参数,它允许您比简单地计算(x ** y) % z更有效地计算xy模z:

>>> x, y, z = 1234567890, 2345678901, 17>>> pow(x, y, z)            # almost instantaneous6

相比之下,(x ** y) % z在我的机器上一分钟内没有给出相同值的结果。

原始字符串中的反斜杠仍然可以转义引号。看这个:

>>> print repr(r"aaa\"bbb")'aaa\\"bbb'

请注意,反斜杠和双引号都存在于最后的字符串中。

因此,您不能以反斜杠结束原始字符串:

>>> print repr(r"C:\")SyntaxError: EOL while scanning string literal>>> print repr(r"C:\"")'C:\\"'

发生这种情况是因为实现原始字符串是为了帮助编写正则表达式,而不是编写Windows路径。阅读Gotcha-Windows文件名中的反斜杠中关于此的长讨论。

序列乘法和反射操作数

>>> 'xyz' * 3'xyzxyzxyz'
>>> [1, 2] * 3[1, 2, 1, 2, 1, 2]
>>> (1, 2) * 3(1, 2, 1, 2, 1, 2)

我们使用反射(交换)操作数获得相同的结果

>>> 3 * 'xyz''xyzxyzxyz'

它是这样工作的:

>>> s = 'xyz'>>> num = 3

要计算表达式s*num,解释器调用S.___mul___(数字)

>>> s * num'xyzxyzxyz'
>>> s.__mul__(num)'xyzxyzxyz'

要计算表达式num*s,解释器调用___mul___数目

>>> num * s'xyzxyzxyz'
>>> num.__mul__(s)NotImplemented

如果调用返回未执行,则解释器调用如果操作数具有不同的类型,则反射操作S.___rmul___(数字)

>>> s.__rmul__(num)'xyzxyzxyz'

http://docs.python.org/reference/datamodel.html#object.rmul

枚举不同的起始索引

enumerate这个答案中已经部分覆盖,但最近我发现了enumerate的一个更隐藏的功能,我认为它值得自己的帖子而不仅仅是评论。

从Python 2.6开始,您可以在其第二个参数中指定enumerate的起始索引:

>>> l = ["spam", "ham", "eggs"]>>> list(enumerate(l))>>> [(0, "spam"), (1, "ham"), (2, "eggs")]>>> list(enumerate(l, 1))>>> [(1, "spam"), (2, "ham"), (3, "eggs")]

我发现它非常有用的一个地方是当我枚举对称矩阵的条目时。由于矩阵是对称的,我可以通过仅迭代上面的三角形来节省时间,但在这种情况下,我必须在内部for循环中使用enumerate和不同的起始索引来正确跟踪行索引和列索引:

for ri, row in enumerate(matrix):for ci, column in enumerate(matrix[ri:], ri):# ci now refers to the proper column index

奇怪的是,enumerate的这种行为在help(enumerate)中没有记录,只有在在线留档中。

不“隐藏”,但相当有用,不常用

像这样快速创建字符串连接函数

 comma_join = ",".joinsemi_join  = ";".join
print comma_join(["foo","bar","baz"])'foo,bar,baz

能够创建比引号,逗号混乱更优雅的字符串列表。

l = ["item1", "item2", "item3"]

取而代之的是

l = "item1 item2 item3".split()

对象数据模型

您可以在您自己的类的语言中覆盖任何运算符。有关完整列表,请参阅此页面。一些示例:

  • 您可以覆盖任何运算符(* + - / // % ^ == < > <= >= .等)。所有这些都是通过覆盖对象中的__mul____add__等来完成的。您甚至可以覆盖__rmul__等内容以单独处理your_object*something_elsesomething_else*your_object.是属性访问(a.b),可以通过使用__getattr__覆盖以处理任何任意b。这里还包括使用__mul__1的__mul__0。

  • 您可以创建自己的切片语法(a[stuff]),这可能非常复杂,并且与列表中使用的标准语法完全不同(numpy在其数组中有一个很好的例子),使用您喜欢的,:的任何组合,使用Slice对象。

  • 特别处理语言中许多关键字发生的情况。包括delinimportnot

  • 处理当使用对象调用许多内置函数时会发生什么。标准__int____str__等在这里,但__len____reversed____abs__和三个参数__pow__也是如此(用于模幂)。

python 3中的元组解包

在python 3中,您可以使用与函数定义中的可选参数相同的语法进行元组解包:

>>> first,second,*rest = (1,2,3,4,5,6,7,8)>>> first1>>> second2>>> rest[3, 4, 5, 6, 7, 8]

但是一个鲜为人知且功能更强大的功能允许您拥有未知数量的元素在列表的中间

>>> first,*rest,last = (1,2,3,4,5,6,7,8)>>> first1>>> rest[2, 3, 4, 5, 6, 7]>>> last8

插入vs追加

不是一个功能,但可能会很有趣

假设你想在列表中插入一些数据,然后反转它。最简单的方法是

count = 10 ** 5nums = []for x in range(count):nums.append(x)nums.reverse()

然后你想:从一开始就插入数字怎么样?所以:

count = 10 ** 5nums = []for x in range(count):nums.insert(0, x)

如果我们设置count=10**6,它会慢1000倍;这是因为插入是O(n^2),而追加是O(n)。

造成这种差异的原因是插入必须在每次调用时移动列表中的每个元素;追加只需在列表末尾添加元素(有时它必须重新分配所有内容,但它仍然要快得多)

namedtuple是一个元组

>>> node = namedtuple('node', "a b")>>> node(1,2) + node(5,6)(1, 2, 5, 6)>>> (node(1,2), node(5,6))(node(a=1, b=2), node(a=5, b=6))>>>

更多的实验来回应评论:

>>> from collections import namedtuple>>> from operator import *>>> mytuple = namedtuple('A', "a b")>>> yourtuple = namedtuple('Z', "x y")>>> mytuple(1,2) + yourtuple(5,6)(1, 2, 5, 6)>>> q = [mytuple(1,2), yourtuple(5,6)]>>> q[A(a=1, b=2), Z(x=5, y=6)]>>> reduce(operator.__add__, q)(1, 2, 5, 6)

所以,namedtupletuple有趣子类型。

模块在其命名空间中导出一切

包括从其他模块导入的名称!

# this is "answer42.py"from operator import *from inspect  import *

现在测试可以从模块导入什么。

>>> import answer42>>> answer42.__dict__.keys()['gt', 'imul', 'ge', 'setslice', 'ArgInfo', 'getfile', 'isCallable', 'getsourcelines', 'CO_OPTIMIZED', 'le', 're', 'isgenerator', 'ArgSpec', 'imp', 'lt', 'delslice', 'BlockFinder', 'getargspec', 'currentframe', 'CO_NOFREE', 'namedtuple', 'rshift', 'string', 'getframeinfo', '__file__', 'strseq', 'iconcat', 'getmro', 'mod', 'getcallargs', 'isub', 'getouterframes', 'isdatadescriptor', 'modulesbyfile', 'setitem', 'truth', 'Attribute', 'div', 'CO_NESTED', 'ixor', 'getargvalues', 'ismemberdescriptor', 'getsource', 'isMappingType', 'eq', 'index', 'xor', 'sub', 'getcomments', 'neg', 'getslice', 'isframe', '__builtins__', 'abs', 'getmembers', 'mul', 'getclasstree', 'irepeat', 'is_', 'getitem', 'indexOf', 'Traceback', 'findsource', 'ModuleInfo', 'ipow', 'TPFLAGS_IS_ABSTRACT', 'or_', 'joinseq', 'is_not', 'itruediv', 'getsourcefile', 'dis', 'os', 'iand', 'countOf', 'getinnerframes', 'pow', 'pos', 'and_', 'lshift', '__name__', 'sequenceIncludes', 'isabstract', 'isbuiltin', 'invert', 'contains', 'add', 'isSequenceType', 'irshift', 'types', 'tokenize', 'isfunction', 'not_', 'istraceback', 'getmoduleinfo', 'isgeneratorfunction', 'getargs', 'CO_GENERATOR', 'cleandoc', 'classify_class_attrs', 'EndOfBlock', 'walktree', '__doc__', 'getmodule', 'isNumberType', 'ilshift', 'ismethod', 'ifloordiv', 'formatargvalues', 'indentsize', 'getmodulename', 'inv', 'Arguments', 'iscode', 'CO_NEWLOCALS', 'formatargspec', 'iadd', 'getlineno', 'imod', 'CO_VARKEYWORDS', 'ne', 'idiv', '__package__', 'CO_VARARGS', 'attrgetter', 'methodcaller', 'truediv', 'repeat', 'trace', 'isclass', 'ior', 'ismethoddescriptor', 'sys', 'isroutine', 'delitem', 'stack', 'concat', 'getdoc', 'getabsfile', 'ismodule', 'linecache', 'floordiv', 'isgetsetdescriptor', 'itemgetter', 'getblock']>>> from answer42 import getmembers>>> getmembers<function getmembers at 0xb74b2924>>>>

这是一个很好的理由不from x import *和定义__all__ =

运算符可以作为函数调用:

from operator import addprint reduce(add, [1,2,3,4,5,6])

的简单性:

>>> 'str' in 'string'True>>> 'no' in 'yes'False>>>

这是我喜欢Python的地方,我见过很多不是很pythonic的习语:

if 'yes'.find("no") == -1:pass

动态添加的属性

如果您考虑通过调用它们向类添加一些属性,这可能会很有用。这可以通过覆盖使用点操作数时调用的#0成员函数来完成。所以,让我们看一个虚拟类,例如:

class Dummy(object):def __getattribute__(self, name):f = lambda: 'Hello with %s'%namereturn f

当你实例化一个Dummy对象并执行一个方法调用时,你会得到以下结果:

>>> d = Dummy()>>> d.b()'Hello with b'

最后,您甚至可以将属性设置为您的类,以便可以动态定义它。如果您使用Python Web框架并希望通过解析属性名称进行查询,这可能会很有用。

我在github上有一个要点,里面有这个简单的代码和一个朋友在Ruby上做的等价物。

保重!

在运行时更改函数标签:

>>> class foo:...   def normal_call(self): print "normal_call"...   def call(self):...     print "first_call"...     self.call = self.normal_call
>>> y = foo()>>> y.call()first_call>>> y.call()normal_call>>> y.call()normal_call...

我不确定这在Python文档中的哪个位置(或者是否),但是对于python 2. x(至少2.5和2.6,我刚刚尝试过),可以使用括号调用print语句。如果你想轻松地将一些Python 2. x代码移植到Python 3. x,这会很有用。

示例:print('We want Moshiach Now')应该打印We want Moshiach Now在python 2.5、2.6和3. x中工作。

此外,可以在Python 2和3中使用括号调用not运算符:not Falsenot(False)应该都返回True

父母语也可以与其他语句和运算符一起使用。

编辑:将括号放在not运算符(可能还有任何其他运算符)周围不是一个好主意,因为它可能会导致令人惊讶的情况,就像这样(这种情况发生是因为括号实际上围绕1):

>>> (not 1) == 9False
>>> not(1) == 9True

对于某些值(我认为它不是有效的标识符名称),这也可以起作用,如下所示:not'val'应该返回Falseprint'We want Moshiach Now'应该返回We want Moshiach Now。(但not552会引发NameError,因为它是一个有效的标识符名称)。

Python有“私有”变量

以双下划线开始而不是结束的变量变得私有,而不仅仅是按照惯例。实际上__var变成了_Classname__var,其中Classname是创建变量的类。它们不被继承,也不能被覆盖。

>>> class A:...     def __init__(self):...             self.__var = 5...     def getvar(self):...             return self.__var...>>> a = A()>>> a.__varTraceback (most recent call last):File "", line 1, inAttributeError: A instance has no attribute '__var'>>> a.getvar()5>>> dir(a)['_A__var', '__doc__', '__init__', '__module__', 'getvar']>>>

除了前面提到的haridsv之外:

>>> foo = bar = baz = 1>>> foo, bar, baz(1, 1, 1)

也可以这样做:

>>> foo, bar, baz = 1, 2, 3>>> foo, bar, baz(1, 2, 3)

根本不是一个隐藏的功能,但仍然很好:

import os.path as op
root_dir = op.abspath(op.join(op.dirname(__file__), ".."))

在操作路径时保存大量字符!

可以说,这本身不是一个编程功能,但非常有用,我还是会发布它。

$ python -m http.server

$ wget http://<ipnumber>:8000/filename在其他地方。

如果您仍在运行较旧(2. x)版本的Python:

$ python -m SimpleHTTPServer

您还可以指定端口,例如python -m http.server 80(因此,如果您在服务器端拥有根,则可以省略url中的端口)

Python3中的Unicode标识符:

>>> 'Unicode字符_تكوين_Variable'.isidentifier()True>>> Unicode字符_تكوين_Variable='Python3 rules!'>>> Unicode字符_تكوين_Variable'Python3 rules!'

将字符串相乘以使其重复

print "SO"*5

SOSOSOSOSO

commands.getoutput

如果你想得到一个直接输出到stdoutstderr的函数的输出,就像os.system的情况一样,#3来救援。整个模块都很棒。

>>> print commands.getoutput('ls')myFile1.txt    myFile2.txt    myFile3.txt    myFile4.txt    myFile5.txtmyFile6.txt    myFile7.txt    myFile8.txt    myFile9.txt    myFile10.txtmyFile11.txt   myFile12.txt   myFile13.txt   myFile14.txt   module.py

曾经使用过xrange(INT)而不是range(INT)……它的内存占用更少,并且并不真正依赖于整数的大小。耶!!这不是很好吗?

getattr接受第三个参数

getattr(obj, attribute_name, default)就像:

try:return obj.attributeexcept AttributeError:return default

除了attribute_name可以是任何字符串。

这对鸭子打字非常有用。也许你有类似的东西:

class MyThing:passclass MyOtherThing:passif isinstance(obj, (MyThing, MyOtherThing)):process(obj)

(顺便说一句,isinstance(obj, (a,b))意味着isinstance(obj, a) or isinstance(obj, b)。)

当你创建一种新的东西时,你需要将它添加到出现的任何地方的元组中。(当重新加载模块或以两个名称导入同一个文件时,这种结构也会导致问题。这种情况比人们愿意承认的要多。)但相反,你可以说:

class MyThing:processable = Trueclass MyOtherThing:processable = Trueif getattr(obj, 'processable', False):process(obj)

添加继承,它会变得更好:所有可处理对象的示例都可以从

class Processable:processable = True

但是你不必说服每个人从你的基类继承,只是为了设置一个属性。

MapReduce使用map和Reduce函数

用这种方式创建一个简单的sum产品:

def sumprod(x,y):return reduce(lambda a,b:a+b, map(lambda a, b: a*b,x,y))

例子:

In [2]: sumprod([1,2,3],[4,5,6])Out[2]: 32

简单的内置基准测试工具

Python标准库附带了一个非常易于使用的基准测试模块,称为“timeit”。您甚至可以从命令行使用它来查看几种语言结构中哪一种最快。

例如,

% python -m timeit 'r = range(0, 1000)' 'for i in r: pass'10000 loops, best of 3: 48.4 usec per loop
% python -m timeit 'r = xrange(0, 1000)' 'for i in r: pass'10000 loops, best of 3: 37.4 usec per loop

列表中的无限递归

>>> a = [1,2]>>> a.append(a)>>> a[1, 2, [...]]>>> a[2][1, 2, [...]]>>> a[2][2][2][2][2][2][2][2][2] == aTrue

虽然不是很pythonic,但您可以使用#0写入文件

print>>outFile, 'I am Being Written'

补充说明

这种形式有时被称为“print雪佛龙。”在这种形式下,>>之后的第一个表达式必须评估为“类似文件”的对象,特别是一个具有write()方法如上所述。通过这种扩展形式,该随后的表达式打印到这个文件对象。如果第一个表达式的计算结果为None,然后sys.stdout用作文件输出。

string-escapeunicode-escape编码

假设您有一个来自外部源的字符串,其中包含\n\t等。如何将它们转换为换行符或制表符?只需使用string-escape编码解码字符串!

>>> print sHello\nStack\toverflow>>> print s.decode('string-escape')HelloStack   overflow

另一个问题。您有正常的字符串与Unicode文字,如\u01245。如何使其工作?只需使用unicode-escape编码解码字符串!

>>> s = '\u041f\u0440\u0438\u0432\u0456\u0442, \u0441\u0432\u0456\u0442!'>>> print s\u041f\u0440\u0438\u0432\u0456\u0442, \u0441\u0432\u0456\u0442!>>> print unicode(s)\u041f\u0440\u0438\u0432\u0456\u0442, \u0441\u0432\u0456\u0442!>>> print unicode(s, 'unicode-escape')Привіт, світ!

#1压扁#0

#0内置函数可用于#1#2s一起,提供了一种方便的方法来展平#2中的#2

Python 2.7.1 (r271:86832, May 27 2011, 21:41:45)[GCC 4.2.1 (Apple Inc. build 5664)] on darwinType "help", "copyright", "credits" or "license" for more information.>>> l = [[1, 2, 3], [4, 5], [6], [7, 8, 9]]>>> sum(l, [])[1, 2, 3, 4, 5, 6, 7, 8, 9]

博格模式

这是Alex Martelli的杀手。Borg的所有实例共享状态。这消除了使用单例模式的需要(当状态共享时实例无关紧要),并且相当优雅(但对于新类来说更复杂)。

foo的值可以在任何实例中重新分配,并且都将更新,您甚至可以重新分配整个判决。Borg是完美的名字,阅读更多这里

class Borg:__shared_state = {'foo': 'bar'}def __init__(self):self.__dict__ = self.__shared_state# rest of your class here

这对于共享事件来控制并发是完美的。

在接受它的IDE中激活自动完成(如IDLE、Editra、IEP),而不是:“嗨”。(然后你点击选项卡),你可以在IDE中作弊,只需制作(并且你加热选项卡)(正如你所看到的,开头没有单引号),因为它只会遵循最新的标点符号,就像当你添加:并按回车键时,它会直接添加缩进,不知道它是否会做出改变,但它不再是提示:)

这里有两个复活节彩蛋:


一个在python本身:

>>> import __hello__Hello world...

Werkzeug模块中的另一个,揭示起来有点复杂,这里是:

通过查看Werkzeug的源代码,在werkzeug/__init__.py中,有一行应该引起您的注意:

'werkzeug._internal':   ['_easteregg']

如果你有点好奇,这应该会让你看看werkzeug/_internal.py,在那里,你会发现一个_easteregg()函数,它接受一个wsgi应用程序的参数,它还包含一些bas64编码的数据和2个嵌套函数,如果在查询字符串中找到一个名为macgybarchakku的参数,它们似乎会做一些特别的事情。

因此,要揭示这个复活节彩蛋,似乎您需要将应用程序包装在_easteregg()函数中,让我们开始:

from werkzeug import Request, Response, run_simplefrom werkzeug import _easteregg
@Request.applicationdef application(request):return Response('Hello World!')
run_simple('localhost', 8080, _easteregg(application))

现在,如果您运行应用程序并访问http://localhost:8080/?macgybarchakku,您应该会看到复活节彩蛋。

这是我在调试类型错误时使用的一个有用的函数

def typePrint(object):print(str(object) + " - (" + str(type(object)) + ")")

它只是打印输入,然后是类型,例如

>>> a = 101>>> typePrint(a)101 - (<type 'int'>)
for line in open('foo'):print(line)

这相当于(但更好):

f = open('foo', 'r')for line in f.readlines():print(line)f.close()

一次一个屏幕打印多行字符串

隐藏在site._Printer类中的不是真正有用的功能,其license对象是一个实例。后者在调用时打印Python许可证。可以创建另一个相同类型的对象,传递一个字符串-例如文件的内容-作为第二个参数,并调用它:

type(license)(0,open('textfile.txt').read(),0)()

这将一次打印由一定数量的行分割的文件内容:

...file row 21file row 22file row 23
Hit Return for more, or q (and Return) to quit:

脚本(和doctest字符串)的交互式调试

我不认为这是广为人知的,但是将这行添加到任何python脚本中:

import pdb; pdb.set_trace()

将导致PDB调试器在代码中的该点弹出运行光标。我认为,更鲜为人知的是,您可以在doctest中使用同一行:

""">>> 1 in (1,2,3)Becomes>>> import pdb; pdb.set_trace(); 1 in (1,2,3)"""

然后,您可以使用调试器检查doctest环境。您不能真正单步执行doctest,因为每一行都是自主运行的,但它是调试doctest全局和环境的绝佳工具。

在Python 2中,您可以通过用反引号将表达式括起来来生成表达式的字符串表示形式:

 >>> `sorted`'<built-in function sorted>'

这在python 3. X中消失了。

不是编程功能,但在将Python与bashshell scripts一起使用时很有用。

python -c"import os; print(os.getcwd());"

请参阅python留档。在编写更长的Python脚本时需要注意的其他事项可以在这次讨论中看到。

Python对非常意想不到的事情有例外:

进口

这允许您在缺少库时导入替代方案

try:import jsonexcept ImportError:import simplejson as json

迭代:

for循环在内部执行此操作,并捕获StopIteration:

iter([]).next()Traceback (most recent call last):File "<pyshell#4>", line 1, in <module>iter(a).next()StopIteration

断言

>>> try:...     assert []... except AssertionError:...     print "This list should not be empty"This list should not be empty

虽然这对于一次检查来说更加冗长,但可以通过这种方式缩短多次检查混合异常和具有相同错误消息的布尔运算符。

舍入整数:Python有函数round,它返回双精度类型的数字:

 >>> print round(1123.456789, 4)1123.4568>>> print round(1123.456789, 2)1123.46>>> print round(1123.456789, 0)1123.0

这个函数有一个神奇的属性:

 >>> print round(1123.456789, -1)1120.0>>> print round(1123.456789, -2)1100.0

如果您需要一个整数作为结果,请使用int转换类型:

 >>> print int(round(1123.456789, -2))1100>>> print int(round(8359980, -2))8360000

谢谢你Gregor

一些很酷的功能,减少和运营商。

>>> from operator import add,mul>>> reduce(add,[1,2,3,4])10>>> reduce(mul,[1,2,3,4])24>>> reduce(add,[[1,2,3,4],[1,2,3,4]])[1, 2, 3, 4, 1, 2, 3, 4]>>> reduce(add,(1,2,3,4))10>>> reduce(mul,(1,2,3,4))24

Python的位置和关键字扩展可以动态使用,而不仅仅是从存储的列表中使用。

l=lambda x,y,z:x+y+za=1,2,3print l(*a)print l(*[a[0],2,3])

它通常对这样的事情更有用:

a=[2,3]l(*(a+[3]))

口述理解

>>> {i: i**2 for i in range(5)}{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Python留档

维基百科条目

集合理解

>>> {i**2 for i in range(5)}set([0, 1, 4, 16, 9])

Python留档

维基百科条目

不是真正的隐藏功能,而是可能派上用场的东西。

用于循环遍历列表中的项目

for x, y in zip(s, s[1:]):