"if x: return x" 문구를 피하는 피톤식 방법
다른 4가지 메서드를 순차적으로 호출하여 특정 상태를 확인하고 Truthy를 반환할 때마다 즉시 반환하는 메서드가 있습니다(다음 메서드는 체크하지 않음)하는 방법이 있습니다.
def check_all_conditions():
x = check_size()
if x:
return x
x = check_color()
if x:
return x
x = check_tone()
if x:
return x
x = check_flavor()
if x:
return x
return None
많은 수하물 코드 같은데.두 줄의 if 스테이트먼트 대신 다음과 같은 것을 하고 싶습니다.
x and return x
하지만 그건 잘못된 Python이야.심플하고 우아한 솔루션을 놓치고 있는 건가요?덧붙여서, 이 4가지 체크 방법은 비용이 많이 들 수 있기 때문에 여러 번 전화하고 싶지 않습니다.
마르틴의 훌륭한 대답 대신, 당신은 체인으로 묶을 수 있습니다.or
값,즉 truthy 값이 None
값이: truthy:
def check_all_conditions():
return check_size() or check_color() or check_tone() or check_flavor() or None
데모:
>>> x = [] or 0 or {} or -1 or None
>>> x
-1
>>> x = [] or 0 or {} or '' or None
>>> x is None
True
루프를 사용할 수 있습니다.
conditions = (check_size, check_color, check_tone, check_flavor)
for condition in conditions:
result = condition()
if result:
return result
이를 통해 조건의 수를 가변으로 만들 수 있다는 추가 이점이 있습니다.
+(Python 3 버전, Python 2 버전 사용)를 사용하여 일치하는 첫 번째 값을 얻을 수 있습니다.
try:
# Python 2
from future_builtins import map, filter
except ImportError:
# Python 3
pass
conditions = (check_size, check_color, check_tone, check_flavor)
return next(filter(None, map(lambda f: f(), conditions)), None)
하지만 이게 더 읽기 쉽다면 논쟁의 여지가 있다.
또 다른 옵션은 제너레이터 식을 사용하는 것입니다.
conditions = (check_size, check_color, check_tone, check_flavor)
checks = (condition() for condition in conditions)
return next((check for check in checks if check), None)
바꾸지 마세요
다양한 답변에서 알 수 있듯이 이를 수행하는 다른 방법이 있습니다.원래 코드만큼 명확한 것은 없습니다.
timgeb와 사실상 같은 답변이지만, 더 나은 포맷을 위해 괄호를 사용할 수 있습니다.
def check_all_the_things():
return (
one()
or two()
or five()
or three()
or None
)
Colly의 법칙에 따르면 다음 두 가지 문제를 구분하여 이 코드를 보다 읽기 쉽게 만들 수 있습니다.
- 어떤 것을 확인해야 합니까?
- 한 가지가 사실로 돌아왔나요?
두 가지 기능으로 나뉩니다.
def all_conditions():
yield check_size()
yield check_color()
yield check_tone()
yield check_flavor()
def check_all_conditions():
for condition in all_conditions():
if condition:
return condition
return None
이를 통해 다음을 피할 수 있습니다.
- 복잡한 논리 구조
- 아주 긴 줄
- 반복
...선형으로 읽기 쉬운 흐름을 유지합니다.
또, 고객의 상황에 따라서는, 보다 좋은 기능명을 생각해 낼 수 있기 때문에, 한층 더 읽기 쉬워집니다.
이것은 Martijns의 첫 번째 예시의 변형입니다.또한 단락을 허용하기 위해 "콜러블 컬렉션" 스타일을 사용합니다.
루프를 할 수 .any
conditions = (check_size, check_color, check_tone, check_flavor)
return any(condition() for condition in conditions)
:any
는 부울값을 반환하기 때문에 체크의 정확한 반환값이 필요한 경우 이 솔루션은 작동하지 않습니다. any
하지 않다14
,'red'
,'sharp'
,'spicy'
됩니다.True
.
쓰려고 요?if x: return x
두두 한??
def check_all_conditions():
x = check_size()
if x: return x
x = check_color()
if x: return x
x = check_tone()
if x: return x
x = check_flavor()
if x: return x
return None
이것은 당신이 가지고 있던 것보다 덜 반복적이지만 IMNSHO는 꽤 부드럽게 읽힌다.
이 목적을 위해 만들어진 빌트인에 대해 언급하지 않은 것이 매우 놀랍습니다.
def check_all_conditions():
return any([
check_size(),
check_color(),
check_tone(),
check_flavor()
])
이 구현이 가장 명확하지만 첫 번째 구현이 다음과 같은 경우에도 모든 체크를 평가합니다.True
.
첫 번째 실패한 체크에서 정지해야 할 경우 를 사용하여 목록을 단순한 값으로 변환하는 것을 고려하십시오.
def check_all_conditions():
checks = [check_size, check_color, check_tone, check_flavor]
return reduce(lambda a, f: a or f(), checks, False)
reduce(function, iterable[, initializer])
: 으로 두 왼쪽에서 오른쪽으로 두 개의 인수의 함수를 누적하여 반복 가능한 항목에 적용하여 반복 가능한 값을 단일 값으로 줄입니다.왼쪽 인수 x는 누적값, 오른쪽 인수 y는 반복가능으로부터의 갱신값입니다.됩니다.
고객님의 경우:
lambda a, f: a or f()
는, 어큐뮬레이터의 입니다.a
현재 체크 " " " " 입니다.f()
- 아, 아, 아! - 아, 아, 아!True
a
- 아, 아, 아! - 아, 아, 아!True
,f()
평가되지 않습니다.checks
」)이 되어 있습니다.f
람다에서 항목)False
않으면 않고 「이렇게 된다」가 됩니다.그렇지 않으면 체크가 이루어지지 않고 결과는 항상 다음과 같습니다.True
any
★★★★★★★★★★★★★★★★★」reduce
기능 프로그래밍을 위한 기본 도구입니다.이것들, 그것도 훌륭하게 훈련해 주셨으면 합니다!
동일한 코드 구조를 원하는 경우 3진문을 사용할 수 있습니다!
def check_all_conditions():
x = check_size()
x = x if x else check_color()
x = x if x else check_tone()
x = x if x else check_flavor()
return x if x else None
이거 보면 되게 선명하고 좋은 것 같아요.
데모:
저는 @phil-frost에 이어 @wayne-werner's가 가장 좋은 답입니다.
흥미로운 점은 함수가 많은 다른 데이터 유형을 반환한다는 사실에 대해 아무도 언급하지 않았다는 것입니다. 그러면 추가 작업을 수행하기 위해 x 유형 자체를 검사해야 합니다.
그래서 저는 @PhilFrost의 응답을 하나의 유형을 유지한다는 아이디어와 혼합하고 싶습니다.
def all_conditions(x):
yield check_size(x)
yield check_color(x)
yield check_tone(x)
yield check_flavor(x)
def assessed_x(x,func=all_conditions):
for condition in func(x):
if condition:
return x
return None
「 」라는 점에 해 주세요.x
되지만, '인수'도 있습니다.all_conditions
서 모든 함수가 '체크함수', '체크 함수는 '체크'로 표시됩니다.x
후 반송하다True
""False
여 . . . .func
all_conditions
「」를 사용할 수 .assessed_x(x)
를 통해 를 전달할 수 있습니다func
.
★★★★★★★★★★★★★★★★★★★★★★★.x
하나의 체크가 통과되는 즉시, 하지만 항상 같은 타입이 됩니다.
.check_
True
""False
수표가 되다
if check_size(x):
return x
#etc
「」라고 가정했을 .x
( 수 할 수 .check
어쨌든 그걸 수정하는 건 아니겠죠
@timgeb's tim @ 。 동안 저는 을 표현하고 .None
return
이 필요 .or
되고 첫 none-zero,, none-zero, none-empty, none-none이 반환됩니다.★★★★★★★★★★★★★★★★★★★★★★★·None
됩니다.None
,,,, !!
나의 ★★★★★★★★★★★★★★★★★.check_all_conditions()
을 사용하다
def check_all_conditions():
return check_size() or check_color() or check_tone() or check_flavor()
「」를 사용합니다.timeit
number=10**7
나는 많은 제안들의 실행 시간을 살펴보았다.비교하기 위해 나는 단지 그것을 사용했을 뿐이다.random.random()
또는 "return"을 반환하는 None
난수를 바탕으로 합니다.전체 코드는 다음과 같습니다.
import random
import timeit
def check_size():
if random.random() < 0.25: return "BIG"
def check_color():
if random.random() < 0.25: return "RED"
def check_tone():
if random.random() < 0.25: return "SOFT"
def check_flavor():
if random.random() < 0.25: return "SWEET"
def check_all_conditions_Bernard():
x = check_size()
if x:
return x
x = check_color()
if x:
return x
x = check_tone()
if x:
return x
x = check_flavor()
if x:
return x
return None
def check_all_Martijn_Pieters():
conditions = (check_size, check_color, check_tone, check_flavor)
for condition in conditions:
result = condition()
if result:
return result
def check_all_conditions_timgeb():
return check_size() or check_color() or check_tone() or check_flavor() or None
def check_all_conditions_Reza():
return check_size() or check_color() or check_tone() or check_flavor()
def check_all_conditions_Phinet():
x = check_size()
x = x if x else check_color()
x = x if x else check_tone()
x = x if x else check_flavor()
return x if x else None
def all_conditions():
yield check_size()
yield check_color()
yield check_tone()
yield check_flavor()
def check_all_conditions_Phil_Frost():
for condition in all_conditions():
if condition:
return condition
def main():
num = 10000000
random.seed(20)
print("Bernard:", timeit.timeit('check_all_conditions_Bernard()', 'from __main__ import check_all_conditions_Bernard', number=num))
random.seed(20)
print("Martijn Pieters:", timeit.timeit('check_all_Martijn_Pieters()', 'from __main__ import check_all_Martijn_Pieters', number=num))
random.seed(20)
print("timgeb:", timeit.timeit('check_all_conditions_timgeb()', 'from __main__ import check_all_conditions_timgeb', number=num))
random.seed(20)
print("Reza:", timeit.timeit('check_all_conditions_Reza()', 'from __main__ import check_all_conditions_Reza', number=num))
random.seed(20)
print("Phinet:", timeit.timeit('check_all_conditions_Phinet()', 'from __main__ import check_all_conditions_Phinet', number=num))
random.seed(20)
print("Phil Frost:", timeit.timeit('check_all_conditions_Phil_Frost()', 'from __main__ import check_all_conditions_Phil_Frost', number=num))
if __name__ == '__main__':
main()
결과는 다음과 같습니다.
Bernard: 7.398444877040768
Martijn Pieters: 8.506569201346597
timgeb: 7.244275416364456
Reza: 6.982133448743038
Phinet: 7.925932800076634
Phil Frost: 11.924794811353031
위의 Martijns의 첫 번째 예에서는 루프 내의 if를 회피할 수 있습니다.
Status = None
for c in [check_size, check_color, check_tone, check_flavor]:
Status = Status or c();
return Status
이 방법은 조금 틀에서 벗어나지만, 최종 결과는 간단하고 읽기 쉬우며 보기 좋다고 생각합니다.
은 '다'입니다.raise
함수 중 하나가 truthy로 평가되고 결과가 반환되는 경우 예외입니다.수 .
def check_conditions():
try:
assertFalsey(
check_size,
check_color,
check_tone,
check_flavor)
except TruthyException as e:
return e.trigger
else:
return None
필요한 것은,assertFalsey
중 되었을 때 : "truthy"는 과 같습니다.
def assertFalsey(*funcs):
for f in funcs:
o = f()
if o:
raise TruthyException(o)
위의 내용은 평가할 함수에 대한 인수를 제공하도록 수정될 수 있다.
'우리에게 필요한 것'이 있을 예요.TruthyException
그 자체입니다.는 " " 를 제공합니다.object
예외를 경우:
class TruthyException(Exception):
def __init__(self, obj, *args):
super().__init__(*args)
self.trigger = obj
물론 원래의 기능을 보다 일반적인 것으로 변경할 수 있습니다.
def get_truthy_condition(*conditions):
try:
assertFalsey(*conditions)
except TruthyException as e:
return e.trigger
else:
return None
result = get_truthy_condition(check_size, check_color, check_tone, check_flavor)
하면 '어느 쪽인가', '어느 쪽인가', '어느 쪽인가', '어느 쪽인가', '인가'를 하고 있기 때문에 조금 수 있습니다.if
스테이트먼트 및 예외 처리. 이 되지 않기 수 것으로 한 에 대한 히트는 할 필요가 .True
수천 배의 가치를 지닌다.
피토닉 방식은 reduce(누군가 이미 말한 대로) 또는 retertools(아래 그림처럼) 중 하나를 사용하는 것이지만, 단순히 오퍼레이터의 단락을 사용하는 것만으로 더 선명한 코드가 생성되는 것 같습니다.
from itertools import imap, dropwhile
def check_all_conditions():
conditions = (check_size,\
check_color,\
check_tone,\
check_flavor)
results_gen = dropwhile(lambda x:not x, imap(lambda check:check(), conditions))
try:
return results_gen.next()
except StopIteration:
return None
Python 3.8이 필요한 경우 "할당식"의 새로운 기능을 사용하여 if-else 체인을 다소 덜 반복적으로 만들 수 있습니다.
def check_all_conditions():
if (x := check_size()): return x
if (x := check_color()): return x
if (x := check_tone()): return x
if (x := check_flavor()): return x
return None
「」를 사용합니다.max
:
def check_all_conditions():
return max(check_size(), check_color(), check_tone(), check_flavor()) or None
과거에 딕트를 사용한 스위치/케이스 스테이트먼트의 흥미로운 실장을 몇 가지 본 적이 있기 때문에 이 답변에 도달했습니다.미친 짓이다using_complete_sentences_for_function_names
, (그래서)check_all_conditions
.status
(1) (1을 참조해 주세요.
def status(k = 'a', s = {'a':'b','b':'c','c':'d','d':None}) :
select = lambda next, test : test if test else next
d = {'a': lambda : select(s['a'], check_size() ),
'b': lambda : select(s['b'], check_color() ),
'c': lambda : select(s['c'], check_tone() ),
'd': lambda : select(s['d'], check_flavor())}
while k in d : k = d[k]()
return k
하면 각 Select를 .check_FUNCTION
즉 피한다, 피하다check_FUNCTION() if check_FUNCTION() else next
이치노이치노력하다 loopdict 될 시킵니다.
로는 실행 할 수 , 일부 .k
★★★★★★★★★★★★★★★★★」s
★★k='c',s={'c':'b','b':None}
는 테스트 수를 줄이고 원래 처리 순서를 반대로 합니다.
timeit
fellows는 스택에 레이어 한두 개를 추가하는 비용과 dict lookup에 드는 비용에 대해 불평할 수 있지만, 당신은 코드의 아름다움에 더 관심이 있는 것 같습니다.
또는 다음과 같은 간단한 구현이 있습니다.
def status(k=check_size) :
select = lambda next, test : test if test else next
d = {check_size : lambda : select(check_color, check_size() ),
check_color : lambda : select(check_tone, check_color() ),
check_tone : lambda : select(check_flavor, check_tone() ),
check_flavor: lambda : select(None, check_flavor())}
while k in d : k = d[k]()
return k
- pep8이 아니라 문장 대신 하나의 간결한 서술어를 사용한다는 의미입니다.OP가 코딩 규약을 따르고 있거나 기존 코드 베이스 중 하나를 사용하거나 코드 베이스의 간결한 용어를 고려하지 않을 수 있습니다.
언급URL : https://stackoverflow.com/questions/36117583/pythonic-way-to-avoid-if-x-return-x-statements
'programing' 카테고리의 다른 글
업데이트된 vuex 상태에 대한 vue 수명 주기 방법 (0) | 2022.10.30 |
---|---|
배열의 첫 번째 인덱스를 반환하는 NumPy 함수가 있습니까? (0) | 2022.10.29 |
목록에서 항목 색인 찾기 (0) | 2022.10.29 |
VueX 사용 시 Vue 목록에서 Prop로 ID만 전달하고 전체 데이터 항목 전달 (0) | 2022.10.29 |
jQuery의 .click - 사용자 함수에 매개 변수 전달 (0) | 2022.10.29 |