S přiřazením výrazů v Pythonu 3.8, proč musíme použít `` as` v with`?

hlasů
17

Nyní, když PEP 572 byl přijat, Python 3.8 je předurčen k tomu mít přiřazení výrazů , takže můžeme použít výraz přiřazení v withpsát při pohledu zcela přirozené

with f := open('file.txt'):
    for l in f:
        print(f)

namísto

with open('file.txt') as f:
    for l in f:
        print(f)

a to bude fungovat stejně jako předtím.

K čemu dělá asklíčové slovo s withprohlášením v Pythonu 3.8? Není to proti Zen Python: „Mělo by být jedno - a pokud možno pouze jeden - zřejmý způsob, jak to udělat.“ ?

Položena 17/07/2018 v 14:44
zdroj uživatelem
V jiných jazycích...                            


1 odpovědí

hlasů
20

TL, DR : Chování není stejný pro oba konstrukty, i když by být zřetelné rozdíly mezi příklady 2.

Měli byste se téměř nikdy potřebovat :=v withprohlášení, a někdy je to velmi špatné. V případě pochybností, vždy with ... as ...když budete potřebovat spravovaný objekt uvnitř withbloku.


V roce with context_manager as managed, managedje vázán na návratovou hodnotu z context_manager.__enter__(), zatímco v with managed := context_manager, managedse váže na context_managersebe a návratová hodnota __enter__()volání metody je zlikvidovat . Chování je téměř shodné pro otevřené soubory, protože jejich __enter__metoda vrací self.

První výňatek zhruba analogická

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

k tomu, že asforma bude

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

tedy with f := open(...)by se nastaven fna návratovou hodnotu open, přičemž with open(...) as fse váže fna návratovou hodnotu implicitní __enter__() volání metody.

Nyní, v případě, že soubory a potoků , file.__enter__()vrátí self-li se to podaří, tak chování těchto dvou přístupů je téměř stejný - rozdíl je pouze v případě, že __enter__způsobí výjimku.

Skutečnost, že přiřazení výrazy se často pracují místo asje ošidná, protože existuje mnoho tříd, kde _mgr.__enter__()se vrací objekt, který je odlišný od self. V tomto případě výraz přiřazení funguje jinak: kontextové manager přiřazen namísto řízeného objektu . Například unittest.mock.patchje kontext manažer, který vrátí falešný objekt. V dokumentaci k němu má následující příklad:

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

Teď, když to bylo být psán používat výraz přiřazení chování by bylo něco jiného:

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

mock_thing Nyní je vázán na kontextu správce namísto nového makety objektu.

Odpovězeno 17/07/2018 v 14:44
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more