조건에서 할당 할 수 있습니까?
조건에 할당 할 수 있습니까?
예를 들어.
if (a=some_func()):
# Use a
시도해 보지 않겠습니까?
>>> def some_func():
... return 2
...
>>> a = 2
>>> if (a = some_func()):
File "<stdin>", line 1
if (a = some_func()):
^
SyntaxError: invalid syntax
>>>
그래서 안돼.
아니요, BDFL은 그 기능을 좋아하지 않았습니다.
내가 앉은 자리에서 "Benevolent Dictator For Life"인 Guido van Rossum은 Python을 가능한 한 단순하게 유지하기 위해 열심히 싸웠습니다. 우리는 그가 내린 결정 중 일부에 대해 고민 할 수 있습니다. 하지만 파이썬을 설계하는위원회가 없었고, 대신 한 디자이너의 감성을 통해 필터링하는 장점에 기반을 둔 신뢰할 수있는 "자문위원회" 가 하나의 멋진 언어 인 IMHO를 만들어 냈습니다.
업데이트-원래 답변이 하단 근처에 있습니다.
Python 3.8은 PEP572 를 가져올 것입니다 .
Abstract
이것은 NAME : = expr 표기법을 사용하여 표현식 내의 변수에 할당하는 방법을 생성하기위한 제안입니다. 새 예외 인 TargetScopeError가 추가되고 평가 순서에 한 가지 변경 사항이 있습니다.
https://lwn.net/Articles/757713/
"PEP 572 혼란"은 BDFL (Benevolent dictator for life) Guido van Rossum이 이끄는 2018 Python Language Summit 세션의 주제였습니다. PEP 572는 언어에 할당 표현식 (또는 "인라인 할당")을 추가하려고하지만, python-ideas에 대한 여러 차례의 라운드 후에도 python-dev 메일 링 목록의 여러 방대한 스레드에 대한 오랜 논의를 보았습니다. 이러한 스레드는 종종 논쟁의 여지가 많았으며 많은 사람들이 아마 방금 조정했을 정도로 방대했습니다. 정상 회담에서 Van Rossum은 기능 제안에 대한 개요를 제공했으며이를 수용하는 경향이 있지만 향후 이러한 종류의 스레드 폭발을 방지하는 방법에 대해서도 논의하고 싶었습니다.
https://www.python.org/dev/peps/pep-0572/#examples-from-the-python-standard-library
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 코드는 더 규칙적으로 보이고 다중 중첩 된 경우를 피합니다. (이 예의 출처는 부록 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 ()을 호출하고 if 라인에서 .match ()를 호출하면 코드가
이해하기 어렵게 만듭니다.
흐름:
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 루프를 사용하면 무한 루프, 할당 및 조건이 필요하지 않습니다. 또한 단순히 함수 호출을 조건으로 사용하는 루프와이를 조건으로 사용하지만 실제 값을 사용하는 루프 사이에 부드러운 병렬을 생성합니다.
Fork 저수준 UNIX 세계의 예 :
if pid := os.fork(): # Parent code else: # Child code
원래 답변
http://docs.python.org/tutorial/datastructures.html
Note that in Python, unlike C, assignment cannot occur inside expressions. C programmers may grumble about this, but it avoids a common class of problems encountered in C programs: typing = in an expression when == was intended.
also see:
http://effbot.org/pyfaq/why-can-t-i-use-an-assignment-in-an-expression.htm
Not directly, per this old recipe of mine -- but as the recipe says it's easy to build the semantic equivalent, e.g. if you need to transliterate directly from a C-coded reference algorithm (before refactoring to more-idiomatic Python, of course;-). I.e.:
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, a very idiomatic Pythonic form for your specific case, if you know exactly what falsish value somefunc
may return when it does return a falsish value (e.g. 0
), is
for a in iter(somefunc, 0):
# use a
so in this specific case the refactoring would be pretty easy;-).
If the return could be any kind of falsish value (0, None
, ''
, ...), one possibility is:
import itertools
for a in itertools.takewhile(lambda x: x, iter(somefunc, object())):
# use a
but you might prefer a simple custom generator:
def getwhile(func, *a, **k):
while True:
x = func(*a, **k)
if not x: break
yield x
for a in getwhile(somefunc):
# use a
Yes, but only from Python 3.8 and onwards.
PEP 572 proposes Assignment Expressions and has already been accepted.
Quoting the Syntax and semantics part of the 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]
In your specific case, you will be able to write
if a := some_func():
# Use a
No. Assignment in Python is a statement, not an expression.
Thanks to Python 3.8 new feature it will be possible to do such a thing from this version, although not using =
but Ada-like assignment operator :=
. Example from the docs:
# Handle a matched regex
if (match := pattern.search(data)) is not None:
# Do something with match
You can define a function to do the assigning for you:
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)
One of the reasons why assignments are illegal in conditions is that it's easier to make a mistake and assign True or False:
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
In Python 3 True and False are keywords, so no risk anymore.
참고URL : https://stackoverflow.com/questions/2603956/can-we-have-assignment-in-a-condition
'developer tip' 카테고리의 다른 글
앱이 내 뷰의 백그라운드로 들어갈 때를 감지하는 가장 좋은 방법은 무엇입니까? (0) | 2020.10.28 |
---|---|
Angular 4를 사용하여 창 크기 감지 (0) | 2020.10.28 |
테이블 표시, redshift에서 동등한 테이블 설명 (0) | 2020.10.28 |
SEGV_MAPERR은 무엇입니까? (0) | 2020.10.28 |
jQuery serialize는 확인란을 등록하지 않습니다. (0) | 2020.10.28 |