# cf.Query

class `cf.``Query`(operator, value, units=None, exact=True, attr=None)

  Bases: `object`

  Store a query operation.

  A query is an inquiry into any object that ascertains if, and possibly where, the object satisfies the inquiry. For example the query “is this strictly less than 3?” may be applied to the number 2.5, giving a result of `True`. The same query may be applied to the number 3 to give a result of `False`.

  The query operation is an operator with a right hand side operand. For example, an operator could be “strictly less than (<)” and a right hand side operand could 3.

  Such a query (such as “is this strictly less than 3?”) may be evaluated for an arbitrary left hand side operand, x (i.e. “is x strictly less than 3?”).

  The result of the query is dependent on the object type of left hand side operand, x. For example, if x is an integer then evaluating “is x strictly less than 3?” will result in a boolean; but if x is a `numpy` array then “is x strictly less than 3?” will likely produce a numpy array of booleans.

  The query is evaluated for an object with its `evaluate` method or equivalently with the `==` operator. For example to test the query “is this strictly less than 3?” against the number 2, any of the following three methods may be used:

      >>> q = cf.Query('lt', 3)
      >>> q.evaluate(2)
      True
      >>> 2 == q
      True
      >>> q == 2
      True

  The inverse of the query may be evaluated with the `!=` operator:

      >>> q = cf.Query('wi', [3, 5])
      >>> q.evaluate(4)
      True
      >>> 4 == q
      True
      >>> 4 != q
      False
      >>> q != 6
      True

  The following operators are supported:

  operator | Description | Constructor
  --- | --- | ---
  `'lt'` | Is x strictly less than a value? | `cf.lt`
  `'le'` | Is x less than or equal to a value? | `cf.le`
  `'gt'` | Is x strictly greater than a value? | `cf.gt`
  `'ge'` | Is x greater than or equal to a value? | `cf.ge`
  `'eq'` | Is x equal to a value? | `cf.eq`
  `'ne'` | Is x not equal to a value? | `cf.ne`
  `'wi'` | Is x within a given range of values (range bounds included)? | `cf.wi`
  `'wo'` | Is x without a given range of values (range bounds excluded)? | `cf.wo`
  `'set'` | Is x equal to any member of a collection? | `cf.set`
  `'contain'` | If cells are defined, is value contained in a cell of x? otherwise is x equal to a value? | `cf.contain`

  For the `'wi'`, `'wo '` and `'set'` operators, if the left hand side operand supports broadcasting over its elements (such as a `numpy` array or a `cf.Field` object) then each element is tested independently. For example:

      >>> q = cf.Query('wi', [3, 4])
      >>> q == [2, 3, 4]
      False
      >>> print q == numpy.array([2, 3, 4])
      [ False  True  True]

  As a convenience, for each operator there is an identically named constructor function which returns the appropriate `cf.Query` object. For example:

      >>> cf.lt(3)
      <CF Query: lt 3>

  Compound queries

  Multiple queries may be logically combined with the bitwise `&` and `|` operators to form a new `cf.Query` object. For example:

      >>> q = cf.ge(3)
      >>> r = cf.lt(5)
      >>> s = q & r
      >>> s
      >>> <CF Query: [(ge 3) & (lt 5)]>
      >>> 4 == s
      True
      >>> t = q | r
      >>> t
      <CF Query: [(ge 3) | (lt 5)]>
      >>> 2 == t
      True

  Compound queries may be combined further:

      >>> u = s | cf.wi(1.5, 2.5)
      >>> u
      <CF Query: [[(ge 3) & (lt 5)] | (wi (1.5, 2.5))]>
      >>> 2 == u
      True
      >>> u & t
      <CF Query: [[[(ge 3) & (lt 5)] | (wi (1.5, 2.5))] & [(ge 3) | (lt 5)]]>

  If any of the component queries are for left hand side operand attributes, then these are retained in a compound query. For example:

      >>> q = cf.ge(3)
      >>> r = cf.lt(5, attr='bar')
      >>> s = q & r
      >>> s = e.addattr('foo')
      >>> s
      <CF Query: foo[(ge 3) & bar(lt 5)]>

  In this example,

      >>> x == s

  is equivalent to

      >>> (x.foo == cf.ge(3)) & (x.foo.bar == cf.lt(5))

  Attributes

  Attribute | Description
  --- | ---
  `attr` | An attribute name such that this attribute of the left hand side operand is compared, rather than the operand itself. If there is more than one attribute name then each is interpreted as an attribute of the previous attribute.
  `operator` | The query operation (such as `'lt'`, for example). Always `None` for compound queries.
  `exact` | If False then string values are treated as a regular expressions as understood by the `re` module and are evaluated using the `re.match` method. Ignored for all operators except `'eq'`, `'ne'` and `'set'`.

  Initialization

  Parameters: | operator: `str` The query operator. value: The right hand side of the query operation. units: `str` or `cf.Units`, optional The units of value. By default, the same units, if any, as the left hand side of the query operation are assumed. exact: `bool`, optional If False then string values are treated as a regular expressions as understood by the `re` module and are evaluated using the `re.match` method. Ignored for all operators except `'eq'`, `'ne'` and `'set'`. attr: `str`, optional Specify an attribute (or an attribute of an attribute, etc.) of a left hand side operand which is compared, rather than the operand itself. Example: `cf.Query('ge', 2, attr='ndim')` will return True when evaluated for a numpy array with two or more dimensions. Example: `q=cf.Query('ge', 2, attr='lower_bounds.month')` will compare the `month` attribute of the `lower_bounds` attribute. I.e. `q==x` is equivalent to `cf.Query('ge', 2)==x.lower_bounds.month`.
  Examples: |

      >>> cf.Query('le', 5.6)
      <CF Query: (le 5.6)>
      >>> cf.Query('gt', 5.6, 'metres')
      <CF Query: (gt <CF Data: 5.6 metres>)>
      >>> cf.Query('gt', cf.Data(5.6, 'metres'))
      <CF Query: (gt <CF Data: 5.6 metres>)>
      >>> cf.Query('wi', [2, 56])
      <CF Query: (wi [2, 56])>
      >>> cf.Query('set', [2, 56], 'seconds')
      <CF Query: (set <CF Data: [2, 56] seconds>)>
      >>> cf.Query('set', cf.Data([2, 56], 'seconds'))
      <CF Query: (set <CF Data: [2, 56] seconds>)>
      >>> cf.Query('eq', 'air_temperature')
      <CF Query: (eq 'air_temperature')>
      >>> cf.Query('eq', 'temperature', exact=False)
      <CF Query: (eq 'temperature')>
      >>> cf.Query('gt', 1, attr='ndim')
      <CF Query: ndim(gt 1)>

## Attributes

`attr` |
Examples: |
`exact` |
Examples: |
`operator` |
Examples: |
`value` |
Examples: |

## Methods

`__init__`(operator, value[, units, exact, attr]) | Initialization
`addattr`(attr) | Return a `cf.Query` object with a new left hand side operand attribute to be used during evaluation.
`copy`() | Return a deep copy.
`dump`([display]) | Return a string containing a full description of the instance.
`equals`(other[, traceback]) |
`equivalent`(other[, traceback]) |
`evaluate`(x) | Evaluate the query operation for a given left hand side operand.
`inspect`() | Inspect the object for debugging.