first: The function you always missed in Python
===============================================
.. image:: https://travis-ci.org/hynek/first.svg?branch=master
:target: https://travis-ci.org/hynek/first
:alt: CI Status
``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.
If 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.
N.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]``.
But **not**: ``None``, ``False``, ``[]``, or ``0``.
In JavaScript, they call this “truthy”.
Examples
========
A simple example to get started:
.. code-block:: pycon
>>> from first import first
>>> first([0, None, False, [], (), 42])
42
However, it’s especially useful for dealing with regular expressions in ``if/elif/else`` branches:
.. code-block:: python
import re
from first import first
re1 = re.compile('b(.*)')
re2 = re.compile('a(.*)')
m = first(regexp.match('abc') for regexp in [re1, re2])
if not m:
print('no match!')
elif m.re is re1:
print('re1', m.group(1))
elif m.re is re2:
print('re2', m.group(1))
The optional ``key`` function gives you even *more* selection power.
If you want to return the first even number from a list, just do the following:
.. code-block:: pycon
>>> from first import first
>>> first([1, 1, 3, 4, 5], key=lambda x: x % 2 == 0)
4
``default`` on the other hand allows you to specify a value that is returned if none of the elements is true:
.. code-block:: pycon
>>> from first import first
>>> first([0, None, False, [], ()], default=42)
42
Usage
=====
The package consists of one module consisting of one function:
.. code-block:: python
from first import first
first(iterable, default=None, key=None)
This function returns the first element of ``iterable`` that is true if ``key`` is ``None``.
If there is no true element, the value of ``default`` is returned, which is ``None`` by default.
If 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.
``first`` has no dependencies and should work with any Python available.
Alternatives
============
``first`` brings nothing to the table that wasn’t possible before.
However the existing solutions aren’t very idiomatic for such a common and simple problem.
The following constructs are equivalent to ``first(seq)`` and work since Python 2.6:
.. code-block:: python
next(itertools.ifilter(None, seq), None)
next(itertools.ifilter(bool, seq), None)
next((x for x in seq if x), None)
None of them is as pretty as I’d like them to be.
The ``re`` example from above would look like the following:
.. code-block:: python
next(itertools.ifilter(None, (regexp.match('abc') for regexp in [re1, re2])), None)
next((regexp.match('abc') for regexp in [re1, re2] if regexp.match('abc')), None)
next((match for match in itertools.imap(
operator.methodcaller('match', 'abc'), [re1, re2]) if match), None)
Note that in the second case you have to call ``regexp.match()`` *twice*.
The third example "fixes" that problem but also summons Cthulhu.
For comparison, one more time the ``first``-version:
.. code-block:: python
first(regexp.match('abc') for regexp in [re1, re2])
Idiomatic, clear and readable. Pythonic. :)
----
As 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>`_.
Background
==========
The idea for ``first`` goes back to a discussion I had with `Łukasz Langa`_ about how the ``re`` example above is painful in Python.
We 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.
So 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.
.. _`Łukasz Langa`: https://github.com/ambv
.. :changelog:
History
-------
2.0.2 (2019-03-07)
++++++++++++++++++
- Package tests as part of the dist.
- Update docs.
- Drop unsupported Python versions from CI.
N.B. The code hasn't changed and ``first`` continues to work as before.
2.0.1 (2013-08-04)
++++++++++++++++++
- Make installable on systems that don’t support UTF-8 by default.
- *Backward incompatible*: Drop support for Python older than 2.6, the previous fix gets too convoluted otherwise.
Please don’t use Python < 2.6 anyway.
I beg you.
N.B. that this is a *pure packaging/QA matter*: the module still works perfectly with ancient Python versions.
2.0.0 (2012-10-13)
++++++++++++++++++
- `pred` proved to be rather useless. Changed to `key` which is just a selector. This is a *backward incompatible* change and the reason for going 2.0.
- Add `default` argument which is returned instead of `None` if no true element is found.
1.0.2 (2012-10-09)
++++++++++++++++++
- Fix packaging. I get this never right the first time. :-/
1.0.1 (2012-10-09)
++++++++++++++++++
- Documentation fixes only.
1.0.0 (2012-10-09)
++++++++++++++++++
- Initial release.
Credits
=======
“first” is written and maintained by Hynek Schlawack and various contributors:
- Artem Bezsmertnyi
- Łukasz Langa
- Nick Coghlan
- Vincent Driessen
Raw data
{
"_id": null,
"home_page": "http://github.com/hynek/first/",
"name": "first",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "",
"author": "Hynek Schlawack",
"author_email": "hs@ox.cx",
"download_url": "https://files.pythonhosted.org/packages/b0/a2/78a4e6801fbd789c60888afb8e28ccbe629f9a25137bfafecb363db2fb53/first-2.0.2.tar.gz",
"platform": "",
"description": "first: The function you always missed in Python\n===============================================\n\n.. image:: https://travis-ci.org/hynek/first.svg?branch=master\n :target: https://travis-ci.org/hynek/first\n :alt: CI Status\n\n``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.\nIf 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\u2019t fit your use case.\n\nN.B. I\u2019m using the term \u201ctrue\u201d consistently with Python docs for ``any()`` and ``all()`` \u2014 it means that the value evaluates to true like: ``True``, ``1``, ``\"foo\"``, or ``[None]``.\nBut **not**: ``None``, ``False``, ``[]``, or ``0``.\nIn JavaScript, they call this \u201ctruthy\u201d.\n\n\nExamples\n========\n\nA simple example to get started:\n\n.. code-block:: pycon\n\n >>> from first import first\n >>> first([0, None, False, [], (), 42])\n 42\n\nHowever, it\u2019s especially useful for dealing with regular expressions in ``if/elif/else`` branches:\n\n.. code-block:: python\n\n import re\n\n from first import first\n\n\n re1 = re.compile('b(.*)')\n re2 = re.compile('a(.*)')\n\n m = first(regexp.match('abc') for regexp in [re1, re2])\n if not m:\n print('no match!')\n elif m.re is re1:\n print('re1', m.group(1))\n elif m.re is re2:\n print('re2', m.group(1))\n\nThe optional ``key`` function gives you even *more* selection power.\nIf you want to return the first even number from a list, just do the following:\n\n.. code-block:: pycon\n\n >>> from first import first\n >>> first([1, 1, 3, 4, 5], key=lambda x: x % 2 == 0)\n 4\n\n``default`` on the other hand allows you to specify a value that is returned if none of the elements is true:\n\n.. code-block:: pycon\n\n >>> from first import first\n >>> first([0, None, False, [], ()], default=42)\n 42\n\n\nUsage\n=====\n\nThe package consists of one module consisting of one function:\n\n.. code-block:: python\n\n from first import first\n\n first(iterable, default=None, key=None)\n\nThis function returns the first element of ``iterable`` that is true if ``key`` is ``None``.\nIf there is no true element, the value of ``default`` is returned, which is ``None`` by default.\n\nIf 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.\n\n``first`` has no dependencies and should work with any Python available.\n\n\nAlternatives\n============\n\n``first`` brings nothing to the table that wasn\u2019t possible before.\nHowever the existing solutions aren\u2019t very idiomatic for such a common and simple problem.\n\nThe following constructs are equivalent to ``first(seq)`` and work since Python 2.6:\n\n.. code-block:: python\n\n next(itertools.ifilter(None, seq), None)\n next(itertools.ifilter(bool, seq), None)\n next((x for x in seq if x), None)\n\nNone of them is as pretty as I\u2019d like them to be.\nThe ``re`` example from above would look like the following:\n\n.. code-block:: python\n\n next(itertools.ifilter(None, (regexp.match('abc') for regexp in [re1, re2])), None)\n next((regexp.match('abc') for regexp in [re1, re2] if regexp.match('abc')), None)\n next((match for match in itertools.imap(\n operator.methodcaller('match', 'abc'), [re1, re2]) if match), None)\n\nNote that in the second case you have to call ``regexp.match()`` *twice*.\nThe third example \"fixes\" that problem but also summons Cthulhu.\n\nFor comparison, one more time the ``first``-version:\n\n.. code-block:: python\n\n first(regexp.match('abc') for regexp in [re1, re2])\n\nIdiomatic, clear and readable. Pythonic. :)\n\n----\n\nAs 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>`_.\n\n\nBackground\n==========\n\nThe idea for ``first`` goes back to a discussion I had with `\u0141ukasz Langa`_ about how the ``re`` example above is painful in Python.\nWe figured such a function is missing Python, however it\u2019s rather unlikely we\u2019d get it in and even if, it wouldn\u2019t get in before 3.4 anyway, which is years away as of yours truly is writing this.\n\nSo I decided to release it as a package for now. If it proves popular enough, it may even make it into Python\u2019s stdlib in the end.\n\n\n.. _`\u0141ukasz Langa`: https://github.com/ambv\n\n\n.. :changelog:\n\nHistory\n-------\n\n2.0.2 (2019-03-07)\n++++++++++++++++++\n\n- Package tests as part of the dist.\n- Update docs.\n- Drop unsupported Python versions from CI.\n N.B. The code hasn't changed and ``first`` continues to work as before.\n\n\n2.0.1 (2013-08-04)\n++++++++++++++++++\n\n- Make installable on systems that don\u2019t support UTF-8 by default.\n- *Backward incompatible*: Drop support for Python older than 2.6, the previous fix gets too convoluted otherwise.\n Please don\u2019t use Python < 2.6 anyway.\n I beg you.\n N.B. that this is a *pure packaging/QA matter*: the module still works perfectly with ancient Python versions.\n\n\n2.0.0 (2012-10-13)\n++++++++++++++++++\n\n- `pred` proved to be rather useless. Changed to `key` which is just a selector. This is a *backward incompatible* change and the reason for going 2.0.\n- Add `default` argument which is returned instead of `None` if no true element is found.\n\n1.0.2 (2012-10-09)\n++++++++++++++++++\n\n- Fix packaging. I get this never right the first time. :-/\n\n1.0.1 (2012-10-09)\n++++++++++++++++++\n\n- Documentation fixes only.\n\n1.0.0 (2012-10-09)\n++++++++++++++++++\n\n- Initial release.\n\n\nCredits\n=======\n\n\u201cfirst\u201d is written and maintained by Hynek Schlawack and various contributors:\n\n- Artem Bezsmertnyi\n- \u0141ukasz Langa\n- Nick Coghlan\n- Vincent Driessen\n\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Return the first true value of an iterable.",
"version": "2.0.2",
"project_urls": {
"Homepage": "http://github.com/hynek/first/"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "4062eda58db762d4845c971029becfecf6e85ad71c3bcba7d400598013a222a1",
"md5": "4564ac22c1270c2ab55606459e2469ee",
"sha256": "8d8e46e115ea8ac652c76123c0865e3ff18372aef6f03c22809ceefcea9dec86"
},
"downloads": -1,
"filename": "first-2.0.2-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "4564ac22c1270c2ab55606459e2469ee",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": null,
"size": 5359,
"upload_time": "2019-03-07T10:07:26",
"upload_time_iso_8601": "2019-03-07T10:07:26.535126Z",
"url": "https://files.pythonhosted.org/packages/40/62/eda58db762d4845c971029becfecf6e85ad71c3bcba7d400598013a222a1/first-2.0.2-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b0a278a4e6801fbd789c60888afb8e28ccbe629f9a25137bfafecb363db2fb53",
"md5": "8a45cda7d3f77f0c5af091d10d406821",
"sha256": "ff285b08c55f8c97ce4ea7012743af2495c9f1291785f163722bd36f6af6d3bf"
},
"downloads": -1,
"filename": "first-2.0.2.tar.gz",
"has_sig": false,
"md5_digest": "8a45cda7d3f77f0c5af091d10d406821",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 6964,
"upload_time": "2019-03-07T10:07:28",
"upload_time_iso_8601": "2019-03-07T10:07:28.322717Z",
"url": "https://files.pythonhosted.org/packages/b0/a2/78a4e6801fbd789c60888afb8e28ccbe629f9a25137bfafecb363db2fb53/first-2.0.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2019-03-07 10:07:28",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "hynek",
"github_project": "first",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"tox": true,
"lcname": "first"
}