Python에서 함수를 동적으로 정의하는 방법 소개

不言
풀어 주다: 2019-03-19 10:28:02
앞으로
2767명이 탐색했습니다.

이 글은 Python에서 함수를 동적으로 정의하는 방법을 소개합니다. 필요한 친구들이 참고할 수 있기를 바랍니다.

MIT 라이선스에 따라

Python에는 런타임 시 함수 정의를 단순화하는 구문 설탕이 없습니다. 그러나 이것이 달성하기 불가능하거나 어렵다는 것을 의미하지는 않습니다.

from types import FunctionType

foo_code = compile('def foo(): return "bar"', "<string>", "exec")
foo_func = FunctionType(foo_code.co_consts[0], globals(), "foo")

print(foo_func())
로그인 후 복사

출력:

bar
로그인 후 복사

Analytic

코드를 한 줄씩 살펴보면 언어/통역사 장벽이 얼마나 취약한지 알 수 있습니다.

>>> from types import FunctionType
로그인 후 복사

Python 문서에는 일반적으로 수동으로 생성된 클래스용이 아닌 기능이 나열되어 있지 않습니다(이는 완전히 합리적입니다). 이 문제를 해결하는 방법에는 help(), 검사(내장 메서드를 검사할 수 없음), 그리고 CPython 소스 코드를 검사하는 최종 솔루션의 세 가지 방법이 있습니다. (권장: python tutorial)

이 경우 help()와 검사가 모두 작업을 수행하지만 실제 소스 코드를 보면 데이터 유형에 대한 자세한 내용을 확인할 수 있습니다.

>>> from inspect import signature
>>> signature(FunctionType)
<Signature (code, globals, name=None, argdefs=None, closure=None)>
로그인 후 복사

1. Code

는 내부적으로 외부 세계에 type.CodeType으로 공개되는 PyCode객체입니다. 내장되지 않은 메소드에는 해당 코드 객체를 저장하는 __code__ 속성이 있습니다. Types.CodeType 객체는 내장된 compile() 메서드를 사용하여 런타임에 생성될 수 있습니다.

2. globals

함수가 로컬에서 정의되지 않았지만 매개변수로 전달되거나 기본 매개변수 값으로 제공되거나 클로저 컨텍스트를 통해 제공되는 변수를 참조하는 경우 전역 사전에서 조회됩니다. .

내장된 globals() 메서드는 현재 모듈의 전역 기호 테이블에 대한 참조를 반환하므로 현재 테이블의 상태와 항상 일치하는 사전을 제공하는 데 사용할 수 있습니다. 다른 사전(FunctionType((lambda: bar).__code__, {"bar" : "baz"}, "foo")() == "baz")을 전달할 수도 있습니다.

3. name(선택 사항)

반환된 함수의 __name__ 속성을 제어합니다. 람다(보통 익명성으로 인해 이름이 없음) 및 이름 바꾸기 함수에만 정말 유용합니다.

4.argdefs(선택 사항)

모든 유형의 객체를 포함하는 튜플을 전달하여 기본 인수 값(def foo(bar="baz"))을 제공하는 방법을 제공합니다. (FunctionType((lambda bar: bar).__code__, {}, "foo", (10,))() == 10).

5. 클로저(선택 사항)

(CPython(PyPy, Jython 등)이 아닌 Python VM에서 실행해야 하는 경우 구현 세부 사항에 크게 의존하므로 건드리지 말아야 합니다).

셀 객체의 튜플. 셀 객체를 생성하는 것은 CPython의 내부 구성 요소에 대한 호출이 필요하기 때문에 완전히 간단하지는 않지만 이를 더 쉽게 만들어 주는 라이브러리가 있습니다: exalt(부끄러운 광고). (주석: 이 라이브러리는 저자가 개발했습니다.)

>>> foo_code = compile('def foo(): return "bar"', "<string>", "exec")
로그인 후 복사

compile()은 내장 메서드이므로 문서화도 잘 되어 있습니다.

exec 모드는 함수를 정의하려면 여러 문이 필요하기 때문에 사용됩니다.

>>> foo_func = FunctionType(foo_code.co_consts[0], globals(), "foo")
로그인 후 복사

모든 것을 집계하고 동적으로 생성된 함수를 변수에 할당합니다.

이전 코드 문장으로 컴파일된 함수는 생성된 코드 객체의 첫 번째 상수가 되므로 foo_code를 가리키는 것만으로는 충분하지 않습니다. 이는 생성된 코드 객체가 여러 상수를 포함할 수 있으므로 exec 모드의 직접적인 결과입니다.

>>> print(foo_func())
로그인 후 복사

동적으로 생성된 함수는 다른 함수처럼 호출할 수 있습니다.

마지막으로

실험을 제외하면 동적으로 생성된 함수가 필요한 시나리오는 거의 없습니다.
Python의 내부를 살펴보는 것은 언어에 대해 더 많이 배울 수 있는 좋은 방법입니다.
원하는 경우 통역사/언어 경계를 쉽게 넘나들 수 있습니다.


위 내용은 Python에서 함수를 동적으로 정의하는 방법 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:segmentfault.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿