Python编程语言中有哪些鲜为人知但很有用的特性?
尽量将答案限制在Python核心。
每个回答一个特征。
给出一个例子和功能的简短描述,而不仅仅是文档链接。
使用标题作为第一行标记该特性。
快速链接到答案:
参数解包
牙套
链接比较运算符
修饰符
可变默认参数的陷阱/危险
描述符
字典默认的.get值
所以测试
省略切片语法
枚举
其他/
函数作为iter()参数
生成器表达式
导入该
就地值交换
步进列表
__missing__物品
多行正则表达式
命名字符串格式化
嵌套的列表/生成器推导
运行时的新类型
.pth文件
ROT13编码
正则表达式调试
发送到发电机
交互式解释器中的制表符补全
三元表达式
试着/ / else除外
拆包+打印()函数
与声明
>>> 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]
不是真正的隐藏特性,但是partial对于函数的后期计算非常有用。
你可以在初始调用中绑定尽可能多的或尽可能少的参数到你想要的partial,并在以后使用任何剩余的参数调用它(在这个例子中,我已经将begin/end参数绑定到range,但第二次使用step arg调用它)
请参见文档。
条件赋值
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调用func1,否则调用func2。在这两种情况下,对应的函数将调用参数arg1和arg2。
类似地,以下也成立:
x = (class1 if y == 1 else class2)(arg1, arg2)
其中class1和class2是两个类。
描述符
它们是一大堆核心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 self
return self.fget(obj)
你可以像使用内置属性()一样使用它:
class MyClass(object):
@Property
def foo(self):
return "Foo!"
在Python中,描述符用于实现属性、绑定方法、静态方法、类方法和插槽等。理解它们可以很容易地理解为什么以前看起来像Python“怪癖”的很多东西是这样的。
Raymond Hettinger有一个很棒的教程,在描述它们方面比我做得更好。
按以下方式访问字典元素
属性(属性)。所以如果
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
就地值交换
>>> a = 10
>>> b = 5
>>> a, b
(10, 5)
>>> a, b = b, a
>>> a, b
(5, 10)
赋值语句的右边是一个表达式,用于创建一个新的元组。赋值的左边立即将(未引用的)元组解包为名称a和b。
赋值之后,新的元组不被引用,并标记为垃圾收集,绑定到a和b的值已经交换。
正如Python教程中关于数据结构的部分所述,
注意,多重赋值实际上只是元组打包和序列解包的组合。