programing

'with' 문장에 여러 변수가 있습니까?

kingscode 2022. 11. 8. 21:18
반응형

'with' 문장에 여러 변수가 있습니까?

를 사용하여 둘 이상의 변수를 선언할 수 있습니까?withPython의 스테이트먼트

예를 들어 다음과 같습니다.

from __future__ import with_statement

with open("out.txt","wt"), open("in.txt") as file_out, file_in:
    for line in file_in:
        file_out.write(line)

아니면 동시에 2개의 자원을 청소하는 것이 문제입니까?

Python 3에서는 v3.1과 Python 2.7 이후가 가능합니다.새로운 구문은 멀티콘텍스트 매니저를 지원합니다.

with A() as a, B() as b, C() as c:
    doSomething(a,b,c)

와는 달리contextlib.nested이를 통해 다음 사항이 보증됩니다.a그리고.b그들의 것이 될 것이다__exit__()가 호출되어도C()아니면__enter__()method가 예외를 발생시킵니다.

이전 변수는 이후 정의에서도 사용할 수 있습니다(아래의 h/t Ahmad).

with A() as a, B(a) as b, C(a, b) as c:
    doSomething(a, c)

Python 3.10부터는 괄호를 사용할 수 있습니다.

with (
    A() as a, 
    B(a) as b, 
    C(a, b) as c,
):
    doSomething(a, c)

변수를 여러 줄로 분할하는 경우 Python 3.10 이전 버전에서는 새 줄을 줄 바꿈하기 위해 백슬래시를 사용해야 합니다.

with A() as a, \
     B() as b, \
     C() as c:
    doSomething(a,b,c)

대신 Python이 태플을 만들기 때문에 괄호는 작동하지 않습니다.

with (A(),
      B(),
      C()):
    doSomething(a,b,c)

튜플에는 a가 부족하기 때문에__enter__Atribute에 에러가 표시됩니다(설명할 수 없고 클래스 타입을 식별하지 않습니다).

AttributeError: __enter__

사용하려고 하면as괄호 안에 Python은 해석 시 오류를 포착합니다.

with (A() as a,
      B() as b,
      C() as c):
    doSomething(a,b,c)
SyntaxError: invalid syntax

언제 고쳐지나요?

이 문제는 https://bugs.python.org/issue12782에서 추적하고 있습니다.

PEP 617에서 Python은 원래 파서를 새 파서로 교체한다고 발표했습니다.Python의 원래 파서는 LL(1)이므로 "복수 컨텍스트 관리자"를 구분할 수 없습니다.with (A(), B()):및 "값의 복잡성"with (A(), B())[0]:.

새로운 파서는 괄호로 둘러싸인 여러 콘텍스트 매니저를 적절히 해석할 수 있습니다.새로운 파서는 3.9로 유효하게 되어 있습니다.이 구문은 Python 3.10에서 오래된 파서가 삭제될 때까지 계속 거부될 것으로 보고되었으며, 이 구문 변경은 3.10 릴리즈 노트에 보고되었습니다.그러나, 제 테스트에서는, trinket.io의 Python 3.9.6에서도 동작합니다.

contextlib.nested 는 다음을 지원합니다.

import contextlib

with contextlib.nested(open("out.txt","wt"), open("in.txt")) as (file_out, file_in):

   ...

업데이트:
문서에 대한 견적을 내려면 다음 정보를 참조하십시오.

버전 2.7 이후 폐지:with-statement는 이 기능을 직접 지원합니다(오류가 발생하기 쉬운 혼란스러운 문제는 없습니다).

자세한 내용은 Rafau Dowgird의 답변을 참조하십시오.

Python 3.3부터는 모듈의 클래스를 사용할 수 있습니다.

컨텍스트 인식 개체의 동적 를 관리할 수 있습니다. 즉, 처리할 파일의 수를 모를 때 특히 유용합니다.

매뉴얼에 기재되어 있는 표준적인 사용 사례는 동적 개수의 파일을 관리하는 것입니다.

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # All opened files will automatically be closed at the end of
    # the with statement, even if attempts to open files later
    # in the list raise an exception

일반적인 예를 다음에 나타냅니다.

from contextlib import ExitStack

class X:
    num = 1

    def __init__(self):
        self.num = X.num
        X.num += 1

    def __repr__(self):
        cls = type(self)
        return '{cls.__name__}{self.num}'.format(cls=cls, self=self)

    def __enter__(self):
        print('enter {!r}'.format(self))
        return self.num

    def __exit__(self, exc_type, exc_value, traceback):
        print('exit {!r}'.format(self))
        return True

xs = [X() for _ in range(3)]

with ExitStack() as stack:
    print(stack._exit_callbacks)
    nums = [stack.enter_context(x) for x in xs]
    print(stack._exit_callbacks)
print(stack._exit_callbacks)
print(nums)

출력:

deque([])
enter X1
enter X2
enter X3
deque([<function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86158>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f861e0>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86268>])
exit X3
exit X2
exit X1
deque([])
[1, 2, 3]

대신 이 작업을 수행하고자 합니다.

from __future__ import with_statement

with open("out.txt","wt") as file_out:
    with open("in.txt") as file_in:
        for line in file_in:
            file_out.write(line)

Python 3.10부터는 다음과 같은 구문을 허용하는 괄호화된 컨텍스트 매니저의 새로운 기능이 있습니다.

with (
    A() as a,
    B() as b
):
    do_something(a, b)

.1 표현을 할 수 , 은 여러 Python 3.1+에서처럼 됩니다.with문이 중첩되었습니다.

with A() as a, B() as b:
    suite

와 동등하다

with A() as a:
    with B() as b:
        suite

즉, 두 번째 식에서 에일리어스를 사용할 수 있습니다(db connections/cursor를 사용할 때 유용).

with get_conn() as conn, conn.cursor() as cursor:
    cursor.execute(sql)

콘텍스트 매니저의 작성도 분리할 수 있습니다(__init__및method)__enter__방법)을 사용하여 가독성을 높입니다.이 대신:

with Company(name, id) as company, Person(name, age, gender) as person, Vehicle(brand) as vehicle:
    pass

다음 코드를 쓸 수 있습니다.

company = Company(name, id)
person = Person(name, age, gender)
vehicle = Vehicle(brand)

with company, person, vehicle:
    pass

는, 「」외에 해 주세요.with스테이트먼트는 작성한 오브젝트를 스테이트먼트 밖에서 사용할 수도 있다는 인상을 줍니다.콘텍스트 매니저에 대해서 이것이 사실이 아닌 경우는, 잘못된 인상에 의해서 판독성의 시행이 방해될 가능성이 있습니다.

문서에는 다음과 같이 기재되어 있습니다.

대부분의 콘텍스트 매니저는 1회만 유효하게 사용할 수 있는 방법으로 기술되어 있습니다.이러한 일회용 컨텍스트 매니저는 사용할 때마다 새로 생성해야 합니다. 다시 사용하려고 하면 예외가 발생하거나 올바르게 작동하지 않습니다.

이 일반적인 제한은 일반적으로 컨텍스트 매니저가 사용되는 스테이트먼트의 헤더에 직접 작성하는 것을 권장합니다.

언급URL : https://stackoverflow.com/questions/893333/multiple-variables-in-a-with-statement

반응형