Python 3中高效清洗数值输入并转为Numpy数组的优化方法
locals() Limitations in Python 3.x) Great question! I’ve struggled with this exact problem before—trying to skip repetitive boilerplate when converting function inputs to properly shaped NumPy arrays, only to hit the wall that you can’t reliably update locals() in Python 3.x. Let’s walk through a few clean, low-boilerplate solutions:
1. A Reusable Sanitization Helper Function (Simple & Direct)
Start by writing a single helper function that handles all your input cleaning logic (conversion to array, reshaping, validation, etc.). Then call this helper on each parameter explicitly—this avoids locals() entirely and keeps your code readable.
Example:
import numpy as np def sanitize_input(x, target_shape=None): # Convert to NumPy array (handles lists, tuples, scalars) x_arr = np.asarray(x) # Reshape if target shape is specified if target_shape is not None: x_arr = x_arr.reshape(target_shape) # Add extra validation here (e.g., check for numeric dtypes, non-null values) return x_arr def test_func(a, b): a = sanitize_input(a, target_shape=(2, 2)) b = sanitize_input(b, target_shape=(3,)) # Rest of your logic using sanitized a and b print(f"a shape: {a.shape}, b shape: {b.shape}")
Pros: Straightforward, easy to debug, no "magic" involved. Perfect for functions with a small number of parameters.
2. Use a Decorator for Cross-Function Reusability
If you have multiple functions that need the same input sanitization rules, a decorator can encapsulate the logic entirely, leaving your function bodies focused on business logic.
Example:
import numpy as np from functools import wraps def sanitize_args(target_shapes): """Decorator to sanitize function arguments into NumPy arrays with specified shapes.""" def decorator(func): @wraps(func) def wrapper(*args, **kwargs): # Sanitize positional arguments sanitized_args = [] for arg, shape in zip(args, target_shapes): sanitized_args.append(sanitize_input(arg, shape)) # Sanitize keyword arguments (if needed) sanitized_kwargs = {} for key, arg in kwargs.items(): sanitized_kwargs[key] = sanitize_input(arg, target_shapes[key]) if key in target_shapes else arg return func(*sanitized_args, **sanitized_kwargs) return wrapper return decorator # Usage with positional arguments @sanitize_args(target_shapes=[(2,2), (3,)]) # Maps a -> (2,2), b -> (3,) def test_func(a, b): print(f"a shape: {a.shape}, b shape: {b.shape}") # Usage with keyword arguments @sanitize_args(target_shapes={"a": (2,2), "b": (3,)}) def test_func_kw(a, b): print(f"a shape: {a.shape}, b shape: {b.shape}")
Pros: Zero boilerplate in your actual function logic. Ideal if you need to apply the same sanitization to many functions.
3. Batch-Process Parameters with inspect (For Many Arguments)
If your function has a lot of parameters, use the inspect module to dynamically get and process all arguments, reducing repetition even further.
Example:
import numpy as np import inspect def test_func(a, b, c): # Get all function parameters and their values sig = inspect.signature(test_func) params = sig.bind(*locals().values()).arguments # Define shape rules per parameter (customize this as needed) shape_rules = { "a": (2,2), "b": (3,), "c": (1, 5) } # Sanitize each parameter sanitized_params = { name: sanitize_input(val, shape_rules.get(name)) for name, val in params.items() } # Unpack sanitized values into local variables (safe alternative to locals().update()) a, b, c = sanitized_params.values() # Rest of your logic print(f"a shape: {a.shape}, b shape: {b.shape}, c shape: {c.shape}")
Note: The locals().update() trick won’t reliably update actual local variables in Python 3, so unpacking explicitly is the safe way to go.
Pros: Cuts down on repetition for functions with many parameters.
Why Your Original locals() Approach Fails
Just to clarify: In Python 3.x, locals() returns a snapshot of the current local variables. Any changes you make to this dictionary won’t be reflected back to the actual variable names in the scope. That’s why your original approach doesn’t modify a or b as expected.
内容的提问来源于stack exchange,提问作者jrinker

