code: def binary_operator(op):
      """
      Factory function for making binary operator methods on a Filter subclass.
  
      Returns a function "binary_operator" suitable for implementing functions
      like __and__ or __or__.
      """
      # When combining a Filter with a NumericalExpression, we use this
      # attrgetter instance to defer to the commuted interpretation of the
      # NumericalExpression operator.
      commuted_method_getter = attrgetter(
          method_name_for_op(op, commute=True)
      )
  
      def binary_operator(self, other):
          if isinstance(self, NumericalExpression):
              self_expr, other_expr, new_inputs = self.build_binary_op(
                  op,
                  other,
              )
              return NumExprFilter.create(
                  "({left}) {op} ({right})".format(
                      left=self_expr,
                      op=op,
                      right=other_expr,
                  ),
                  new_inputs,
              )
          elif isinstance(other, NumericalExpression):
              # NumericalExpression overrides numerical ops to correctly handle
              # merging of inputs.  Look up and call the appropriate
              # right-binding operator with ourself as the input.
              return commuted_method_getter(other)(self)
          elif isinstance(other, Term):
              if other.dtype != bool_dtype:
                  raise BadBinaryOperator(op, self, other)
              if self is other:
                  return NumExprFilter.create(
                      "x_0 {op} x_0".format(op=op),
                      (self,),
                  )
              return NumExprFilter.create(
                  "x_0 {op} x_1".format(op=op),
                  (self, other),
              )
          elif isinstance(
              other, int
          ):  # Note that this is true for bool as well
              return NumExprFilter.create(
                  "x_0 {op} {constant}".format(
                      op=op, constant=int(other)
                  ),
                  binds=(self,),
              )
          raise BadBinaryOperator(op, self, other)
  
      binary_operator.__doc__ = "Binary Operator: '%s'" % op
      return binary_operator
  
imports: from itertools import chain
  from operator import attrgetter
  from numpy import float64, nan, nanpercentile
  from catalyst.errors import BadPercentileBounds, NonExistentAssetInTimeFrame, UnsupportedDataType
  from catalyst.lib.labelarray import LabelArray
  from catalyst.lib.rank import is_missing
  from catalyst.pipeline.expression import BadBinaryOperator, FILTER_BINOPS, method_name_for_op, NumericalExpression
  from catalyst.pipeline.mixins import AliasedMixin, CustomTermMixin, DownsampledMixin, LatestMixin, PositiveWindowLengthMixin, RestrictedDTypeMixin, SingleInputMixin
  from catalyst.pipeline.term import ComputableTerm, Term
  from catalyst.utils.input_validation import expect_types
  from catalyst.utils.memoize import classlazyval
  from catalyst.utils.numpy_utils import bool_dtype, repeat_first_axis
label_desc: Use image node_id 2 for calling a global function with example usage: binary_operator(op) and returns: binary_operator, NumExprFilter, commuted_method_getter, NumExprFilter, NumExprFilter, NumExprFilter