Ant*_*ala 26 python python-3.x python-3.8 python-assignment-expression
现在已经接受了PEP 572,Python 3.8注定要有赋值表达式,所以我们可以使用赋值表达式with,即
with (f := open('file.txt')):
for l in f:
print(f)
Run Code Online (Sandbox Code Playgroud)
代替
with open('file.txt') as f:
for l in f:
print(f)
Run Code Online (Sandbox Code Playgroud)
它会像以前一样工作.
as关键字与withPython 3.8中的语句有什么用?这不是针对Python的禅宗:"应该有一个 - 最好只有一个 - 显而易见的方法." ?
当最初提出的功能,它并没有明确规定是否赋值表达式应中括号with和
with f := open('file.txt'):
for l in f:
print(f)
Run Code Online (Sandbox Code Playgroud)
可以工作.但是,在Python 3.8a0中,
with f := open('file.txt'):
for l in f:
print(f)
Run Code Online (Sandbox Code Playgroud)
会引发
File "<stdin>", line 1
with f := open('file.txt'):
^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)
但括号表达式有效.
Ant*_*ala 37
TL; DR:两种结构的行为并不相同,即使两个示例之间没有明显的差异.
你几乎不需要:=在一个with声明中,有时它是非常错误的.如有疑问,请始终with ... as ...在需要with块内的托管对象时使用.
在with context_manager as managed,managed被绑定到返回值的context_manager.__enter__(),而在with (managed := context_manager),managed被绑定到context_manager其本身和的返回值__enter__()方法调用丢弃.打开文件的行为几乎相同,因为它们的__enter__方法返回self.
第一段摘录大致类似于
_mgr = (f := open('file.txt')) # `f` is assigned here, even if `__enter__` fails
_mgr.__enter__() # the return value is discarded
exc = True
try:
try:
BLOCK
except:
# The exceptional case is handled here
exc = False
if not _mgr.__exit__(*sys.exc_info()):
raise
# The exception is swallowed if exit() returns true
finally:
# The normal and non-local-goto cases are handled here
if exc:
_mgr.__exit__(None, None, None)
Run Code Online (Sandbox Code Playgroud)
而as形式将是
_mgr = open('file.txt') #
_value = _mgr.__enter__() # the return value is kept
exc = True
try:
try:
f = _value # here f is bound to the return value of __enter__
# and therefore only when __enter__ succeeded
BLOCK
except:
# The exceptional case is handled here
exc = False
if not _mgr.__exit__(*sys.exc_info()):
raise
# The exception is swallowed if exit() returns true
finally:
# The normal and non-local-goto cases are handled here
if exc:
_mgr.__exit__(None, None, None)
Run Code Online (Sandbox Code Playgroud)
ie with (f := open(...))将设置f为返回值open,而with open(...) as f绑定f到隐式 __enter__()方法调用的返回值.
现在,在的情况下,文件和流,file.__enter__()将返回self如果成功,所以对于这两种方法的行为是几乎唯一的区别是,该事件-同样__enter__会抛出异常.
即赋值表达式会经常加班,而不是事实as是骗人的,因为有很多地方类_mgr.__enter__()返回一个对象,它是不同的self.在这种情况下,赋值表达式的工作方式不同:分配了上下文管理器,而不是托管对象.例如,unittest.mock.patch是一个将返回模拟对象的上下文管理器.它的文档有以下示例:
>>> thing = object()
>>> with patch('__main__.thing', new_callable=NonCallableMock) as mock_thing:
... assert thing is mock_thing
... thing()
...
Traceback (most recent call last):
...
TypeError: 'NonCallableMock' object is not callable
Run Code Online (Sandbox Code Playgroud)
现在,如果要编写它来使用赋值表达式,则行为会有所不同:
>>> thing = object()
>>> with (mock_thing := patch('__main__.thing', new_callable=NonCallableMock)):
... assert thing is mock_thing
... thing()
...
Traceback (most recent call last):
...
AssertionError
>>> thing
<object object at 0x7f4aeb1ab1a0>
>>> mock_thing
<unittest.mock._patch object at 0x7f4ae910eeb8>
Run Code Online (Sandbox Code Playgroud)
mock_thing 现在绑定到上下文管理器而不是新的模拟对象.
| 归档时间: |
|
| 查看次数: |
1406 次 |
| 最近记录: |