class_docstr: A list of blocks that may be computed or pending computation.
  
  In the basic version of BlockList, all blocks are known ahead of time. In
  LazyBlockList, blocks are not yet computed, so the number of blocks may
  change after execution due to block splitting.
class_docstr_tok: ["A","list","of","blocks","that","may","be","computed","or","pending","computation",".","In","the","basic","version","of","BlockList",",","all","blocks","are","known","ahead","of","time",".","In","LazyBlockList",",","blocks","are","not","yet","computed",",","so","the","number","of","blocks","may","change","after","execution","due","to","block","splitting","."]
code: def __init__(
      self,
      blocks: List[ObjectRef[Block]],
      metadata: List[BlockMetadata],
      *,
      owned_by_consumer: bool,
  ):
      assert len(blocks) == len(metadata), (blocks, metadata)
      for b in blocks:
          trace_allocation(b, "BlockList.__init__")
      self._blocks: List[ObjectRef[Block]] = blocks
      self._num_blocks = len(self._blocks)
      self._metadata: List[BlockMetadata] = metadata
      # Whether the block list is owned by consuming APIs, and if so it can be
      # eagerly deleted after read by the consumer.
      self._owned_by_consumer = owned_by_consumer
      # This field can be set to indicate the number of estimated output blocks,
      # since each read task may produce multiple output blocks after splitting.
      self._estimated_num_blocks = None
  
imports: import math
  from typing import Iterator, List, Optional, Tuple
  import numpy
  from ray.data._internal.memory_tracing import trace_allocation
  from ray.data.block import Block, BlockMetadata
  from ray.types import ObjectRef
label_desc: Use image node_id 1 to create a new BlockList object  with example: obj = BlockList(blocks, metadata)