杰瑞科技汇

Python fromfunction如何创建数组?

Of course! Let's break down numpy.fromfunction in detail.

Python fromfunction如何创建数组?-图1
(图片来源网络,侵删)

What is numpy.fromfunction?

numpy.fromfunction is a NumPy function that creates a NumPy array by executing a function over each coordinate of an array. In simpler terms, it generates an array of a given shape, and for each element in that array, it calls a provided function, passing the coordinates (indices) of that element as arguments. The return value of the function becomes the value of the element.

This is a powerful tool for creating arrays with values that are defined by a mathematical relationship over their indices.


The Core Idea: Function of Coordinates

Imagine you want to create a 2D array (a matrix) where the value at any position (i, j) is i + j.

  • For the element at (0, 0), the value should be 0 + 0 = 0.
  • For the element at (0, 1), the value should be 0 + 1 = 1.
  • For the element at (1, 0), the value should be 1 + 0 = 1.
  • For the element at (1, 1), the value should be 1 + 1 = 2.

fromfunction does this automatically. You provide it with a function that knows how to calculate the value from the coordinates, and it builds the entire array for you.

Python fromfunction如何创建数组?-图2
(图片来源网络,侵删)

Syntax and Parameters

numpy.fromfunction(function, shape, **kwargs)

Parameters:

  • function (callable): This is the core of the function. It's a Python function that takes N arguments, where N is the number of dimensions of the output array. The arguments are NumPy arrays representing the coordinates of each point. The function should return a scalar value.
  • shape (tuple of ints): Defines the shape of the output array.
  • dtype (data-type, optional): The data type of the returned array. If not specified, it's inferred from the function's return value.
  • `kwargs**: Additional keyword arguments to pass to thefunction`.

Return Value:

  • An array with the specified shape, where each element's value is determined by applying function to its coordinates.

How It Works: The "Magic" of Broadcasting

This is the most important concept to understand. When you pass a function to fromfunction, NumPy doesn't call it for each element one by one in a slow Python loop. Instead, it does something highly efficient:

  1. It creates N arrays, where N is the number of dimensions.
  2. Each of these arrays has the same shape as the final output.
  3. The first array contains the row index (0, 0, 0, 1, 1, 1, ...) at every position.
  4. The second array contains the column index (0, 1, 2, 0, 1, 2, ...) at every position.
  5. And so on for higher dimensions.

These arrays are then passed to your function. Your function then operates on these entire arrays at once using NumPy's fast, vectorized operations. This is why fromfunction is fast, not because of the function itself, but because of how NumPy prepares the input for it.

Python fromfunction如何创建数组?-图3
(图片来源网络,侵删)

Let's visualize this for a shape of (3, 2):

  1. NumPy creates two coordinate arrays:

    • coords_x (for the first argument, rows):
      [[0 0]
       [1 1]
       [2 2]]
    • coords_y (for the second argument, columns):
      [[0 1]
       [0 1]
       [0 1]]
  2. These two arrays are passed to your function, e.g., lambda x, y: x + y.

  3. The function is executed, performing the addition on the entire arrays:

    [[0+0 0+1]
     [1+0 1+1]
     [2+0 2+1]]
    [[0 1]
     [1 2]
     [2 3]]

    This final matrix is the returned array.


Practical Examples

Example 1: Creating a 2D Addition Table

Let's create a 4x5 array where A[i, j] = i + j.

import numpy as np
def add_indices(i, j):
  """A function that adds its two arguments."""
  return i + j
# Create a 4x5 array using fromfunction
# The shape is (4, 5)
add_table = np.fromfunction(add_indices, (4, 5), dtype=int)
print(add_table)

Output:

[[0 1 2 3 4]
 [1 2 3 4 5]
 [2 3 4 5 6]
 [3 4 5 6 7]]

Notice how the row index i increases down the rows and the column index j increases across the columns.

Example 2: Creating a Distance Grid from the Center

Let's create a 5x5 grid where each cell's value is its Manhattan distance from the center (2, 2). The formula is distance = |x - center_x| + |y - center_y|.

import numpy as np
def manhattan_distance_from_center(x, y):
  """Calculates Manhattan distance from the center of a 5x5 grid."""
  center_x, center_y = 2, 2
  return np.abs(x - center_x) + np.abs(y - center_y)
# Note: We use np.abs for element-wise absolute value
distance_grid = np.fromfunction(manhattan_distance_from_center, (5, 5), dtype=int)
print(distance_grid)

Output:

[[4 3 2 3 4]
 [3 2 1 2 3]
 [2 1 0 1 2]
 [3 2 1 2 3]
 [4 3 2 3 4]]

This creates a beautiful diamond-shaped pattern, which is a common use case for fromfunction.

Example 3: Creating a 3D Array

fromfunction works for any number of dimensions. Let's create a 3x3x3 cube where C[i, j, k] = i * j - k.

import numpy as np
def cube_function(i, j, k):
  """A function of three dimensions."""
  return i * j - k
# Create a 3x3x3 array
cube_array = np.fromfunction(cube_function, (3, 3, 3), dtype=int)
print("Shape of the array:", cube_array.shape)
print("\nFirst 'slice' (k=0):")
print(cube_array[:, :, 0])
print("\nSecond 'slice' (k=1):")
print(cube_array[:, :, 1])

Output:

Shape of the array: (3, 3, 3)
First 'slice' (k=0):
[[ 0  0  0]
 [-1 -2 -3]
 [-2 -4 -6]]
Second 'slice' (k=1):
[-1 -1 -1]
[-2 -3 -4]
[-3 -5 -7]]

You can see how the value of k is subtracted from the i*j product for each slice.


When to Use fromfunction vs. Alternatives

fromfunction is elegant, but not always the most efficient or readable choice.

Method Best For Pros Cons
np.fromfunction Creating arrays where values are a direct function of their indices. - Very concise and expressive for index-based math.
- Can be faster than pure Python loops.
- Can be slower than NumPy's native array creation functions.
- Can be less intuitive for beginners.
- Requires the function to handle NumPy arrays as input.
np.meshgrid Evaluating a function over a grid of points (often for plotting). - More explicit and flexible about the coordinate grids.
- Standard for creating coordinate grids for 3D plots.
- More verbose for simple array creation.
Often requires np.vectorize or a list comprehension to get the final array.
NumPy Math Simple, standard arrays (e.g., of zeros, ones, ranges). - Extremely fast and memory-efficient.
- The standard, idiomatic way.
- Limited to pre-defined patterns (lines, planes, constants).
List Comprehension Complex logic that is hard to vectorize. - Maximum flexibility and readability for complex Python logic.
- Easy to debug.
- Slow for large arrays due to Python interpreter overhead.

A Note on Performance

While fromfunction avoids a slow Python for loop, it still has some overhead from the function call mechanism. For simple patterns, NumPy's built-in functions are almost always faster.

# Fastest way to create an addition table
N, M = 1000, 500
i, j = np.ogrid[:N, :M]
fast_add_table = i + j
# fromfunction is elegant but slower
def add_func(x, y):
    return x + y
elegant_add_table = np.fromfunction(add_func, (N, M), dtype=float)
# List comprehension is the slowest
# slow_add_table = np.array([[i+j for j in range(M)] for i in range(N)])

Summary

Use numpy.fromfunction when:

  • You need to create an array where each element's value is a direct mathematical function of its (row, col, ...) indices.
  • You want a concise, readable way to express this relationship.
  • The logic is too complex for simple np.arange or np.mgrid tricks.

For simple, standard patterns, always prefer native NumPy functions like np.zeros, np.ones, np.arange, and broadcasting (i + j). For complex logic that doesn't fit an index-based function, a list comprehension is often the clearest choice.

分享:
扫描分享到社交APP
上一篇
下一篇