Условные выражения без for в NumPy строятся на трёх базовых механизмах:
векторные условия, булевы маски и поэлементные функции. Это позволяет выразить if / else над массивами целиком, а не поэлементно в цикле.

  1. Булевы маски

Классический паттерн:

import numpy as np
 
X = np.array([1, -2, 3, -4])
 
Y = X.copy()
Y[X < 0] = 0

Здесь условие X < 0 проверяется сразу для всех элементов, а присваивание происходит только там, где маска True.

  1. np.where — векторный if/else
Y = np.where(X > 0, X, 0)

Смысл:

если X > 0 → взять X
иначе → 0

Работает поэлементно, поддерживает broadcasting и не требует копирования входного массива.

  1. Поэлементные функции (np.maximum, np.minimum)

Частный, но очень частый случай:

Y = np.maximum(X, 0)

Эквивалентно:

if x < 0:
    x = 0

Для симметричных ограничений:

Y = np.clip(X, 0, 1)
  1. Комбинация условий
Y = np.where((X > 0) & (X < 10), X, 0)

Важно:
– использовать &, |, ~
– каждое условие брать в скобки

Почему это лучше for:

– нет Python-цикла
– операции выполняются в C-коде NumPy
– код описывает что происходит, а не как

Практическое правило:

– простые условия → np.maximum / minimum / clip
– полноценный if/else → np.where
– сложная логика с побочными эффектами → цикл или Numba

Коротко:
условные выражения без for — это векторизованный if, работающий сразу над всем массивом через маски и функции NumPy.