• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

first.egg-info/H03-May-2022-220145

.travis.ymlH A D07-Mar-2019344 2520

AUTHORS.rstH A D06-Mar-2019171 107

CONTRIBUTING.rstH A D17-Jan-2019888 2316

HISTORY.rstH A D07-Mar-20191.1 KiB4529

LICENSEH A D17-Jan-20191 KiB2016

MANIFEST.inH A D07-Mar-201965 21

MakefileH A D06-Mar-2019165 85

PKG-INFOH A D07-Mar-20198.3 KiB220145

README.rstH A D06-Mar-20194.4 KiB13481

first.pyH A D07-Mar-20191.7 KiB7956

setup.cfgH A D07-Mar-2019102 117

setup.pyH A D07-Mar-20191.6 KiB5245

test_first.pyH A D17-Jan-20191,013 4130

tox.iniH A D07-Mar-2019484 2619

README.rst

1first: The function you always missed in Python
2===============================================
3
4.. image:: https://travis-ci.org/hynek/first.svg?branch=master
5   :target: https://travis-ci.org/hynek/first
6   :alt: CI Status
7
8``first`` is an MIT-licensed Python package with a simple function that returns the first true value from an iterable, or ``None`` if there is none.
9If you need more power, you can also supply a ``key`` function that is used to judge the truth value of the element or a ``default`` value if ``None`` doesn’t fit your use case.
10
11N.B. I’m using the term “true” consistently with Python docs for ``any()`` and ``all()`` — it means that the value evaluates to true like: ``True``, ``1``, ``"foo"``, or ``[None]``.
12But **not**: ``None``, ``False``, ``[]``, or ``0``.
13In JavaScript, they call this “truthy”.
14
15
16Examples
17========
18
19A simple example to get started:
20
21.. code-block:: pycon
22
23   >>> from first import first
24   >>> first([0, None, False, [], (), 42])
25   42
26
27However, it’s especially useful for dealing with regular expressions in ``if/elif/else`` branches:
28
29.. code-block:: python
30
31   import re
32
33   from first import first
34
35
36   re1 = re.compile('b(.*)')
37   re2 = re.compile('a(.*)')
38
39   m = first(regexp.match('abc') for regexp in [re1, re2])
40   if not m:
41      print('no match!')
42   elif m.re is re1:
43      print('re1', m.group(1))
44   elif m.re is re2:
45      print('re2', m.group(1))
46
47The optional ``key`` function gives you even *more* selection power.
48If you want to return the first even number from a list, just do the following:
49
50.. code-block:: pycon
51
52   >>> from first import first
53   >>> first([1, 1, 3, 4, 5], key=lambda x: x % 2 == 0)
54   4
55
56``default`` on the other hand allows you to specify a value that is returned if none of the elements is true:
57
58.. code-block:: pycon
59
60   >>> from first import first
61   >>> first([0, None, False, [], ()], default=42)
62   42
63
64
65Usage
66=====
67
68The package consists of one module consisting of one function:
69
70.. code-block:: python
71
72   from first import first
73
74   first(iterable, default=None, key=None)
75
76This function returns the first element of ``iterable`` that is true if ``key`` is ``None``.
77If there is no true element, the value of ``default`` is returned, which is ``None`` by default.
78
79If a callable is supplied in ``key``, the result of ``key(element)`` is used to judge the truth value of the element, but the element itself is returned.
80
81``first`` has no dependencies and should work with any Python available.
82
83
84Alternatives
85============
86
87``first`` brings nothing to the table that wasn’t possible before.
88However the existing solutions aren’t very idiomatic for such a common and simple problem.
89
90The following constructs are equivalent to ``first(seq)`` and work since Python 2.6:
91
92.. code-block:: python
93
94   next(itertools.ifilter(None, seq), None)
95   next(itertools.ifilter(bool, seq), None)
96   next((x for x in seq if x), None)
97
98None of them is as pretty as I’d like them to be.
99The ``re`` example from above would look like the following:
100
101.. code-block:: python
102
103   next(itertools.ifilter(None, (regexp.match('abc') for regexp in [re1, re2])), None)
104   next((regexp.match('abc') for regexp in [re1, re2] if regexp.match('abc')), None)
105   next((match for match in itertools.imap(
106       operator.methodcaller('match', 'abc'), [re1, re2]) if match), None)
107
108Note that in the second case you have to call ``regexp.match()`` *twice*.
109The third example "fixes" that problem but also summons Cthulhu.
110
111For comparison, one more time the ``first``-version:
112
113.. code-block:: python
114
115   first(regexp.match('abc') for regexp in [re1, re2])
116
117Idiomatic, clear and readable. Pythonic. :)
118
119----
120
121As of version 0.6.5 from 2015, the excellent `boltons package <https://boltons.readthedocs.io/>`_ contains a ``first``-like function as part of its `iterutils module <https://boltons.readthedocs.io/en/latest/iterutils.html#boltons.iterutils.first>`_.
122
123
124Background
125==========
126
127The idea for ``first`` goes back to a discussion I had with `Łukasz Langa`_ about how the ``re`` example above is painful in Python.
128We figured such a function is missing Python, however it’s rather unlikely we’d get it in and even if, it wouldn’t get in before 3.4 anyway, which is years away as of yours truly is writing this.
129
130So I decided to release it as a package for now.  If it proves popular enough, it may even make it into Python’s stdlib in the end.
131
132
133.. _`Łukasz Langa`: https://github.com/ambv
134