sourcecode

우리가 조건부로 과제를 할 수 있습니까?

codebag 2023. 8. 31. 23:51
반응형

우리가 조건부로 과제를 할 수 있습니까?

조건부로 과제를 하는 것이 가능합니까?

예를 들면.

if (a=some_func()):
    # Use a

한 번 해보는 게 어때요?

>>> def some_func():
...   return 2
... 
>>> if (a = some_func()):
  File "<stdin>", line 1
    if (a = some_func()):
          ^
SyntaxError: invalid syntax

그래서, 아니.

업데이트: 이것은 (다른 구문으로) Python 3.8에서 가능합니다.

if a := some_func():

업데이트 - 원본 답변이 맨 아래에 있습니다.

Python 3.8은 PEP572를 도입할 예정입니다.


이것은 다음과 같은 표기법을 사용하여 식 내 변수에 할당하는 방법을 만들기 위한 제안입니다.NAME := expr예외인 새운예외로,,TargetScopeError가 추가되고 평가 순서에 한 가지 변경 사항이 있습니다.

https://lwn.net/Articles/757713/

"PEP 572 혼란"은 생명을 위한 자비로운 독재자(BDFL) Guido van Rossum이 이끄는 2018 파이썬 언어 정상회담 세션의 주제였습니다.PEP 572는 언어에 할당 표현식(또는 "인라인 할당")을 추가하려고 하지만 python-dev 메일링 목록에서 python-dev 메일링 목록의 여러 개의 거대한 스레드에 대한 오랜 논의를 거쳤습니다.이러한 스레드는 종종 논쟁적이었고 많은 사람들이 그냥 무시했을 정도로 분명히 볼륨이 있었습니다.Van Rossum은 정상회담에서 특집 제안의 개요를 발표했는데, 그는 이 제안을 받아들이는 경향이 있는 것처럼 보이지만, 향후 이러한 종류의 스레드 폭발을 피할 수 있는 방법에 대해서도 논의하고 싶었습니다.

https://www.python.org/dev/peps/pep-0572/ #일반적인 표준 웹사이트에서 검색

Python 표준 라이브러리의 예

site.py env_base는 이러한 행에서만 사용되며, 할당은 if가 블록의 "접미사"로 이동할 경우 에 배치됩니다.

현재:

env_base = os.environ.get("PYTHONUSERBASE", None)
if env_base:
    return env_base

향상된 기능:

if env_base := os.environ.get("PYTHONUSERBASE", None):
    return env_base
_pydecimal.py

중첩된 경우 방지하고 들여쓰기 수준 하나를 제거합니다.

현재:

if self._is_special:
    ans = self._check_nans(context=context)
    if ans:
        return ans

향상된 기능:

if self._is_special and (ans := self._check_nans(context=context)):
    return ans

copy.py 코드는 더 규칙적으로 보이고 여러 중첩된 if를 피합니다. (이 예제의 출처는 부록 A 참조)

현재:

reductor = dispatch_table.get(cls)
if reductor:
    rv = reductor(x)
else:
    reductor = getattr(x, "__reduce_ex__", None)
    if reductor:
        rv = reductor(4)
    else:
        reductor = getattr(x, "__reduce__", None)
        if reductor:
            rv = reductor()
        else:
            raise Error(
                "un(deep)copyable object of type %s" % cls)

향상된 기능:

if reductor := dispatch_table.get(cls):
    rv = reductor(x)
elif reductor := getattr(x, "__reduce_ex__", None):
    rv = reductor(4)
elif reductor := getattr(x, "__reduce__", None):
    rv = reductor()
else:
    raise Error("un(deep)copyable object of type %s" % cls)
datetime.py

tz는 s += tz에만 사용되며, 할당을 if 안으로 이동하여 범위를 표시합니다.

현재:

s = _format_time(self._hour, self._minute,
                 self._second, self._microsecond,
                 timespec)
tz = self._tzstr()
if tz:
    s += tz
return s

향상된 기능:

s = _format_time(self._hour, self._minute,
                 self._second, self._microsecond,
                 timespec)
if tz := self._tzstr():
    s += tz
return s

sysconfig.py while 조건에서 fp.readline을 호출하면 .match를 호출하면 if 행이 코드를 더 압축합니다.

이해하기 어렵게 만드는 것.

현재:

while True:
    line = fp.readline()
    if not line:
        break
    m = define_rx.match(line)
    if m:
        n, v = m.group(1, 2)
        try:
            v = int(v)
        except ValueError:
            pass
        vars[n] = v
    else:
        m = undef_rx.match(line)
        if m:
            vars[m.group(1)] = 0

향상된 기능:

while line := fp.readline():
    if m := define_rx.match(line):
        n, v = m.group(1, 2)
        try:
            v = int(v)
        except ValueError:
            pass
        vars[n] = v
    elif m := undef_rx.match(line):
        vars[m.group(1)] = 0

목록 이해의 단순화 목록 이해는 다음 조건을 캡처하여 효율적으로 매핑 및 필터링할 수 있습니다.

results = [(x, y, x/y) for x in input_data if (y := f(x)) > 0]

마찬가지로 하위 표현식은 처음 사용할 때 이름을 지정하여 주 표현식 내에서 재사용할 수 있습니다.

stuff = [[y := f(x), x/y] for x in range(5)]

두 경우 모두 변수 y는 포함하는 범위(즉, 결과 또는 내용과 동일한 수준)에 바인딩됩니다.

조건 값 캡처 if 또는 while 문의 헤더에 효과적으로 할당 식을 사용할 수 있습니다.

# Loop-and-a-half
while (command := input("> ")) != "quit":
    print("You entered:", command)

# Capturing regular expression match objects
# See, for instance, Lib/pydoc.py, which uses a multiline spelling
# of this effect
if match := re.search(pat, text):
    print("Found:", match.group(0))
# The same syntax chains nicely into 'elif' statements, unlike the
# equivalent using assignment statements.
elif match := re.search(otherpat, text):
    print("Alternate found:", match.group(0))
elif match := re.search(third, text):
    print("Fallback found:", match.group(0))

# Reading socket data until an empty string is returned
while data := sock.recv(8192):
    print("Received data:", data)

특히 while 루프에서는 무한 루프, 할당 및 조건을 가질 필요가 없습니다.또한 단순히 함수 호출을 조건으로 사용하는 루프와 이를 조건으로 사용하면서도 실제 값을 사용하는 루프 사이에 원활한 병렬을 생성합니다.

포크 낮은 수준의 UNIX 세계의 예:

if pid := os.fork():
    # Parent code
else:
    # Child code

원답

http://docs.python.org/tutorial/datastructures.html

Python에서는 C와 달리 식 내부에서 할당이 발생할 수 없습니다.C 프로그래머들은 이것에 대해 불평할 수도 있지만, C 프로그램에서 발생하는 일반적인 문제 클래스, 즉 ==가 의도된 경우 식에 =를 입력하는 것을 방지합니다.

참고 항목:

http://effbot.org/pyfaq/why-can-t-i-use-an-assignment-in-an-expression.htm

아니요, BDFL은 그 기능을 좋아하지 않았습니다.

제가 보기에 "평생 은혜로운 독재자"인 Guido van Rossum은 파이썬을 최대한 단순하게 유지하기 위해 열심히 싸웠습니다.우리는 그가 내린 몇 가지 결정에 대해 논쟁할 수 있습니다. 저는 그가 '아니오'라고 더 자주 말했으면 좋았을 것입니다.그러나 파이썬을 설계하는 위원회가 존재하지 않고, 대신에 한 디자이너의 감성을 통해 필터링하는 주로 장점에 기반한 신뢰할 수 있는 "자문 위원회"가 있다는 사실은 IMHO라는 멋진 언어를 만들어냈습니다.

예, 하지만 Python 3.8 이상에서만 사용할 수 있습니다.

PEP 572Assignment Expressions를 제안하며 이미 수락되었습니다.

PEP의 구문의미론 부분 인용:

# Handle a matched regex
if (match := pattern.search(data)) is not None:
    # Do something with match

# A loop that can't be trivially rewritten using 2-arg iter()
while chunk := file.read(8192):
   process(chunk)

# Reuse a value that's expensive to compute
[y := f(x), y**2, y**3]

# Share a subexpression between a comprehension filter clause and its output
filtered_data = [y for x in data if (y := f(x)) is not None]

구체적인 경우, 당신은 다음을 쓸 수 있을 것입니다.

if a := some_func():
    # Use a

직접적인 것은 아닙니다. 의 이 오래된 레시피에 따르면 -- 하지만 레시피에 따르면 의미론적 동등한 것을 구축하는 것이 쉽습니다. 예를 들어 C 코드 참조 알고리즘에서 직접 번역해야 하는 경우(물론 더 관용적인 파이썬으로 리팩터링하기 전에;-).예:

class DataHolder(object):
    def __init__(self, value=None): self.value = value
    def set(self, value): self.value = value; return value
    def get(self): return self.value

data = DataHolder()

while data.set(somefunc()):
  a = data.get()
  # use a

BTW, 당신의 특정 사례에 대한 매우 관용적인 Pythonic 형식, 만약 당신이 정확히 어떤 거짓된 값을 알고 있다면.somefunc 값 잘된값반반면예수환될있하습니다환을못예▁(()을 반환할 때 될 수 .0), 는

for a in iter(somefunc, 0):
  # use a

따라서 이 특정한 경우에는 리팩터링이 매우 쉬울 것입니다;-).

수익률이 어떠한 종류의 허위가치라도 될 수 있다면 (0,None,''...), 한 가지 가능성은 다음과 같습니다.

import itertools

for a in itertools.takewhile(lambda x: x, iter(somefunc, object())):
    # use a

그러나 간단한 사용자 지정 생성기를 선호할 수 있습니다.

def getwhile(func, *a, **k):
    while True:
      x = func(*a, **k)
      if not x: break
      yield x

for a in getwhile(somefunc):
    # use a

아니요. Python에서 할당은 식이 아니라 문입니다.

Python 3.8의 새로운 기능 덕분에 이 버전에서 이러한 작업을 수행할 수 있지만 사용하지는 않습니다.=하지만 에이다와 같은 할당 연산자.:=문서의 예:

# Handle a matched regex
if (match := pattern.search(data)) is not None:
    # Do something with match

할당을 수행하는 기능을 정의할 수 있습니다.

def assign(name, value):
    import inspect
    frame = inspect.currentframe()
    try:
        locals_ = frame.f_back.f_locals
    finally:
        del frame 
    locals_[name] = value
    return value

if assign('test', 0):
    print("first", test)
elif assign('xyz', 123):
    print("second", xyz)

할당 조건이 불법인 이유 중 하나는 실수를 하고 참 또는 거짓을 할당하는 것이 더 쉽기 때문입니다.

some_variable = 5

# This does not work
# if True = some_variable:
#   do_something()

# This only works in Python 2.x
True = some_variable

print True  # returns 5

Python 3에서 True와 False는 키워드이므로 더 이상 위험이 없습니다.

비공식적으로 바다코끼리 연산자로도 알려진 할당 연산자는 PEP572에서 2018년 2월 28일에 만들어졌습니다.

완성도를 위해 3.7과 3.8의 차이를 비교할 수 있도록 관련 부품을 게시합니다.

3.7
---
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
test: or_test ['if' or_test 'else' test] | lambdef
test_nocond: or_test | lambdef_nocond
lambdef: 'lambda' [varargslist] ':' test
lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
or_test: and_test ('or' and_test)*
and_test: not_test ('and' not_test)*
not_test: 'not' not_test | comparison
comparison: expr (comp_op expr)*

3.8
---
if_stmt: 'if' namedexpr_test ':' suite ('elif' namedexpr_test ':' suite)* ['else' ':' suite]
namedexpr_test: test [':=' test]                         <---- WALRUS OPERATOR!!!
test: or_test ['if' or_test 'else' test] | lambdef
or_test: and_test ('or' and_test)*
and_test: not_test ('and' not_test)*
not_test: 'not' not_test | comparison
comparison: expr (comp_op expr)*

언급URL : https://stackoverflow.com/questions/2603956/can-we-have-assignment-in-a-condition

반응형