이 글은 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
코드를 한 줄씩 살펴보면 언어/통역사 장벽이 얼마나 취약한지 알 수 있습니다.
>>> 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!