Python:What the f*ck Python(上) (4)

Output:

>>> [x for x in some_iterable] ['a', 'b'] >>> [(yield x) for x in some_iterable] <generator object <listcomp> at 0x7f70b0a4ad58> >>> list([(yield x) for x in some_iterable]) ['a', 'b'] >>> list((yield x) for x in some_iterable) ['a', None, 'b', None] >>> list(some_func((yield x)) for x in some_iterable) ['a', 'something', 'b', 'something']

说明:
这是CPython在理解和生成器表达式中处理yield的一个错误,在Python 3.8中修复,在Python 3.7中有弃用警告。 请参阅Python错误报告和Python 3.7和Python 3.8的新增条目。

来源和解释可以在这里找到: https://stackoverflow.com/questions/32139885/yield-in-list-comprehensions-and-generator-expressions
相关错误报告:

19. Mutating the immutable! >>> some_tuple = ("A", "tuple", "with", "values") >>> another_tuple = ([1, 2], [3, 4], [5, 6]) >>> some_tuple[2] = "change this" TypeError: 'tuple' object does not support item assignment >>> another_tuple[2].append(1000) # 这里不出现错误 >>> another_tuple ([1, 2], [3, 4], [5, 6, 1000]) >>> another_tuple[2] += [99, 999] TypeError: 'tuple' object does not support item assignment >>> another_tuple ([1, 2], [3, 4], [5, 6, 1000, 99, 999])

说明:
元组中不可变的元素的标识(即元素的地址),如果元素是引用类型,元组的值会随着引用的可变对象的变化而变化。所以 another_tuple[2].append(1000) 是可以的。
+= 操作符在原地修改了列表。元素赋值操作并不工作,但是当异常抛出时,元素已经在原地被修改了。+= 并不是原子操作,而是 extend 和 = 两个动作,这里 = 操作虽然会抛出异常,但 extend 操作已经修改成功了。

20. The disappearing variable from outer scope e = 7 try: raise Exception() except Exception as e: pass

Output: python2

>>> print(e) # prints nothing

Output: python3

>>> print(e) NameError: name 'e' is not defined

说明:
当使用 as 为目标分配异常的时候,将在 except 子句的末尾清除该异常。
这就好像:

except E as N: foo

会被翻译成:

except E as N: try: foo finally: del N

这意味着必须将异常分配给其他名称才能在 except 子句之后引用它。而异常之所以会被清除,是因为附加了回溯信息(trackback),它们与栈帧(stack frame)形成一个引用循环,使得该栈帧中的所有本地变量在下一次垃圾回收发生之前都处于活动状态(不会被回收)。

子句在 Python 中并没有独立的作用域。示例中的所有内容都处于同一作用域内,所以变量 e 会由于执行了 except 子句而被删除。而对于有独立的内部作用域的函数来说情况就不一样了。下面的例子说明了这一点:

def f(x): del(x) print(x) x = 5 y = [5, 4, 3]

Output:

>>>f(x) UnboundLocalError: local variable 'x' referenced before assignment >>>f(y) UnboundLocalError: local variable 'x' referenced before assignment >>> x 5 >>> y [5, 4, 3] 21. When True is actually False True = False if True == False: print("I've lost faith in truth!")

Output:

I've lost faith in truth!

说明:
最初,Python 并没有 bool 型(人们用 0 表示假值, 用非零值比如 1 作为真值)。后来他们添加了 True, False, 和 bool 型,但是,为了向后兼容,他们没法把 True 和 False 设置为常量,只是设置成了内置变量。
Python 3 由于不再需要向后兼容,终于可以修复这个问题了,所以这个例子无法在 Python 3.x 中执行。

22. From filled to None in one instruction... some_list = [1, 2, 3] some_dict = { "key_1": 1, "key_2": 2, "key_3": 3 } some_list = some_list.append(4) some_dict = some_dict.update({"key_4": 4})

Output:

>>> print(some_list) None >>> print(some_dict) None

说明:
大多数修改序列/映射对象的方法,比如 list.append,dict.update,list.sort 等等,都是原地修改对象并返回 None,这样可以避免创建对象的副本来提高性能。

23. Subclass relationships >>> from collections import Hashable >>> issubclass(list, object) True >>> issubclass(object, Hashable) True >>> issubclass(list, Hashable) False

子类关系应该是可传递的,对吧?即,如果 A 是 B 的子类,B 是 C 的子类,那么 A 应该 是 C 的子类。
说明:

Python 中的子类关系并不必须是传递的,任何人都可以在元类中随意定义 __subclasscheck__。

当 issubclass(cls, Hashable) 被调用时,它只是在 cls 中寻找 "__hash__" 方法或继承自 "__hash__" 的方法。

由于 object 是可散列的(hashable),而 list 是不可散列的,所以它打破了这种传递关系。

24. The mysterious key type conversion

class SomeClass(str): pass some_dict = {'s': 42}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdgwf.html