类比无class关键字定义类,如何不用def/lambda定义Python函数?
def or lambda in Python? Great question! Just like classes are created as instances of type, regular functions in Python are actually instances of types.FunctionType. This means we can construct them directly using this type constructor—no def or lambda keywords required. Let’s break down how to do this.
The Core Idea
Functions in Python are objects, and types.FunctionType is their underlying type. To create a function manually, you need two key components:
- A code object: Contains the function’s bytecode, parameter info, and execution logic.
- A global namespace: The set of global variables the function can access.
We’ll use the compile() function to generate the code object (no def/lambda needed) and then pass it to types.FunctionType to create the final function.
Practical Example: Recreate the get_i Function from Your Question
Let’s build the get_i function (which returns self.i) without def or lambda:
import types # Step 1: Compile the function's logic into a code object # We compile the return statement directly—no `def` in sight body_compiled = compile('return self.i', '<get_i_body>', 'exec') # The actual function code lives in `co_consts` of the compiled module code func_code = body_compiled.co_consts[0] # Step 2: Create the function using FunctionType get_i = types.FunctionType( func_code, globals(), # Use the current global namespace name='get_i' # Set the function's name (optional but helpful) ) # Test it with the class you defined class SuperK: pass dct = dict(a=1, i=4, get_i=get_i) Klass2 = type('Klass2', (SuperK,), dct) obj = Klass2() print(obj.get_i()) # Output: 4 (matches the def-based version!)
Example with a Regular Function (e.g., add(a, b))
We can extend this to functions with positional arguments too:
import types # Compile the addition logic add_body = compile('return a + b', '<add_body>', 'exec') add_code = add_body.co_consts[0] # Create the add function add = types.FunctionType( add_code, globals(), name='add' ) print(add(2, 3)) # Output: 5
Advanced: Directly Constructing a Code Object (For Bytecode Nerds)
If you want full control (and don’t mind diving into Python bytecode), you can create a code object manually using types.CodeType. This requires understanding bytecode instructions, but it’s a pure Python way to build functions from scratch:
import types # Construct a code object for `add(a, b) -> a + b` # The bytecode sequence loads `a` and `b`, adds them, then returns the result code = types.CodeType( 2, # Number of positional arguments 0, # Number of keyword-only arguments 2, # Number of local variables 2, # Stack size needed for execution 67, # Flags (0b100001 = function has a return value) b'\x7c\x00\x7c\x01\x17\x00\x53', # Bytecode: LOAD_FAST a, LOAD_FAST b, BINARY_ADD, RETURN_VALUE (), # Constant values used in the function (), # Global names referenced ('a', 'b'), # Local variable names (includes parameters) '<custom_add>', # Filename metadata 'add', # Function name 1, # Starting line number b'', # Line number table (), # Free variables (for closures) () # Cell variables (for nested functions) ) # Create the function add = types.FunctionType(code, globals(), 'add') print(add(4, 6)) # Output: 10
This method is more low-level, but it demonstrates that functions are just objects we can assemble piece by piece.
内容的提问来源于stack exchange,提问作者Toothpick Anemone

