예외를 발생시키는 람다 식 정의
다음과 같은 람다 식을 작성하는 방법
def x():
raise Exception()
다음은 허용되지 않습니다 :
y = lambda : raise Exception()
업데이트 2 : 나는 틀렸다! 파이썬을 스키닝하는 방법은 여러 가지가 있습니다.
y = lambda: (_ for _ in ()).throw(Exception('foobar'))
아니요. Lambdas는 표현식 만 허용합니다. raise ex
진술입니다. 물론, 당신은 범용 모금자를 쓸 수 있습니다 :
def raise_(ex):
raise ex
y = lambda: raise_(Exception('foobar'))
그러나 귀하의 목표가를 피하는 것이라면 def
분명히 자르지 않습니다. 그러나 다음과 같이 조건부로 예외를 발생시킬 수 있습니다.
y = lambda x: 2*x if x < 10 else raise_(Exception('foobar'))
업데이트 : 좋아, 명명 된 함수를 정의하지 않고 예외를 제기 할 수 있습니다 . 당신이 필요로하는 것은 강한 위 (및 주어진 코드의 2.x)입니다.
type(lambda:0)(type((lambda:0).func_code)(
1,1,1,67,'|\0\0\202\1\0',(),(),('x',),'','',1,''),{}
)(Exception())
업데이트 3 : 그리고 python3 강한 위 솔루션 :
type(lambda: 0)(type((lambda: 0).__code__)(
1,0,1,1,67,b'|\0\202\1\0',(),(),('x',),'','',1,b''),{}
)(Exception())
업데이트 4 : 어떤 예외가 발생했는지 신경 쓰지 않으면 매우 간단한 답변을 지적한 @WarrenSpencer에게 감사드립니다 y = lambda: 1/0
.
어때요?
lambda x: exec('raise(Exception(x))')
실제로, 방법이 있지만, 그것은 매우 고안되었습니다.
compile()
내장 함수를 사용하여 코드 객체를 만들 수 있습니다 . 이를 통해 raise
명령문 (또는 그 문제에 대한 다른 명령문)을 사용할 수 있지만 코드 오브젝트 실행이라는 또 다른 문제가 발생합니다. 일반적인 방법은 exec
문 을 사용하는 것이지만 원래 문제로 돌아갑니다. 즉, lambda
(또는 eval()
그 문제에 대해서는 문을 실행할 수 없음 )
해결책은 해킹입니다. lambda
명령문 의 결과와 같은 호출 가능 항목에는 모두 __code__
대체 할 수 있는 속성 이 있습니다. 따라서 호출 가능을 작성하고 __code__
값을 위에서 코드 오브젝트로 바꾸면 명령문을 사용하지 않고 평가할 수있는 것을 얻을 수 있습니다. 그러나이 모든 것을 달성하면 코드가 매우 모호해집니다.
map(lambda x, y, z: x.__setattr__(y, z) or x, [lambda: 0], ["__code__"], [compile("raise Exception", "", "single"])[0]()
위의 내용은 다음과 같습니다.
compile()
호는 예외를 발생하는 부호 객체를 생성;lambda: 0
반환 아무것도하지 않는다하지만 0의 값을 돌려 호출 -이 나중에 위의 코드 개체를 실행하는 데 사용됩니다;는 나머지 인수와 함께 첫 번째 인수
lambda x, y, z
의__setattr__
메소드 를 호출하고 첫 번째 인수를 반환 하는 함수를 작성합니다 ! 때문에, 필요__setattr__
자체가 반환None
;map()
호출의 결과를 소요lambda: 0
하고 사용lambda x, y, z
을 대체 그것의__code__
의 결과에 객체compile()
호출. 이 맵 연산의 결과는에 의해 리턴 된 하나의 항목이있는 목록lambda x, y, z
입니다. 이것이 우리가 이것을 필요로하는 이유입니다. 우리가 즉시lambda
사용__setattr__
하면lambda: 0
객체에 대한 참조를 잃게됩니다 !마지막으로,
map()
호출에 의해 리턴 된 목록의 첫 번째 (및 유일한) 요소 가 실행되어 코드 오브젝트가 호출되어 궁극적으로 원하는 예외가 발생합니다.
작동하지만 (파이썬 2.6에서 테스트 됨) 확실히 그렇지는 않습니다.
마지막 참고 사항 : types
모듈에 액세스 할 수있는 경우 ( import
앞에 명령문 을 사용해야하는 경우 eval
)이 코드를 약간 줄일 types.FunctionType()
수 있습니다 .이를 사용 하면 주어진 코드 객체를 실행하는 함수를 만들 수 있으므로 더미 함수를 만들고 속성 lambda: 0
값을 바꾸는 해킹이 필요하지 않습니다 __code__
.
원하는 모든 것이 임의의 예외를 발생시키는 람다 식이면 잘못된 식으로이를 수행 할 수 있습니다. 예를 들어 lambda x: [][0]
빈 목록의 첫 번째 요소에 액세스하려고하면 IndexError가 발생합니다.
참고 : 이것은 기능이 아닌 해킹입니다. 이 코드는 다른 사람이 보거나 사용할 수있는 코드 골프가 아닌 코드를 사용 하지 마십시오 .
람다 양식으로 작성된 함수 는 명령문을 포함 할 수 없습니다 .
참고 URL : https://stackoverflow.com/questions/8294618/define-a-lambda-expression-that-raises-an-exception
'IT박스' 카테고리의 다른 글
CSS를 사용하여 블록 요소의 순서 전환 (0) | 2020.07.19 |
---|---|
GLib 컴파일 오류 (ffi.h)이지만 libffi가 설치되었습니다. (0) | 2020.07.19 |
해당 속성의 이름에 해당하는 문자열이 주어진 객체 속성에 액세스하는 방법 (0) | 2020.07.18 |
파이썬, 객체 생성 (0) | 2020.07.18 |
(object) 0 == (object) 0이 ((object) 0) .Equals ((object) 0)과 다른 이유는 무엇입니까? (0) | 2020.07.18 |