程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python operations: dynamically defining functions

編輯:Python

stay Python in , There is no syntax sugar that can simplify function definitions at run time . However , This does not mean that it is impossible , Or it is difficult to achieve .

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())

Output :

bar

analyse
View code line by line , You will find language / How fragile the barrier of the interpreter is .

>>> from types import FunctionType
Python Documentation usually does not list the characteristics of classes that are not created manually ( It's perfectly reasonable ). There are three ways to solve this problem :help()、inspect( Cannot view built-in methods )、 And the final solution , Check out CPython Source code .

In this case ,help() And inspect Can complete the work , But look at the actual source code , Will reveal more details about data types .

>>> from inspect import signature
>>> signature(FunctionType)
<Signature (code, globals, name=None, argdefs=None, closure=None)>
  1. code
    Inside is a PyCodeobject, As types.CodeType Opening to the outside world . Non built-in methods have a __code__ attribute , This attribute holds the corresponding code object . With built-in compile() Method , Can be created at run time types.CodeType object .
  2. globals
    If a function references a variable that is not defined locally , Instead, it is transferred as a parameter 、 Provided by default parameter value 、 Or provide... Through closure context , Then it will be in globals Look up in the dictionary .

Built in globals() Method will return a global symbol table for the current module (global symbol table) References to , So it can be used to provide a dictionary that is always consistent with the state of the current table . It is also possible to pass in any other dictionary (FunctionType((lambda: bar).__code__, {"bar" : "baz"}, "foo")() == "baz").

  1. name( Optional )
    Control of the returned function __name__ attribute . Only really right lambdas Useful ( Because of anonymity , They usually have no name ), And rename the function .

  2. argdefs( Optional )
    By passing in a tuple containing an object of any type , Provides a way to supply default parameter values (def

    foo(bar="baz")).(FunctionType((lambda bar: bar).code, {}, "foo", (10,))() == 10).

  3. closure( Optional )
    ( If you need to CPython(PyPy,Jython,…) Other than Python VM In the implementation of , Probably shouldn't touch , Because it relies heavily on implementation details ).

One cell Tuples of objects . establish cell Objects are not entirely straightforward , Because you need to call CPython The internal components of , But there is a library that can make it more convenient :exalt( Shameless advertising ).( Translation notes : This library was developed by the author .)

>>> foo_code = compile('def foo(): return "bar"', "<string>", "exec")

compile() It's a built-in method , Therefore, it is also well documented .

exec Patterns are used , Because defining a function requires multiple statements .

>>> foo_func = FunctionType(foo_code.co_consts[0], globals(), "foo")

Aggregate everything , And assign the dynamically created function to a variable .

The function compiled by the previous code , Becomes the first constant of the generated code object , So just point to foo_code It's not enough . This is a exec The direct consequence of the pattern , Because the generated code object can contain multiple constants .

>>> print(foo_func())
Dynamically generated functions can be called just like other functions .

ending
Besides doing experiments , There are few scenarios where dynamic function creation is required .

play (Toying around) Python Is a good way to learn this language deeply .

if necessary , You can easily cross the interpreter / The boundaries of language .

As always : Don't abuse language ( ok , No harm at all , Right ?)

The above is all the content shared this time , Want to know more python Welcome to official account :Python Programming learning circle , send out “J” Free access to , Daily dry goods sharing


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved