{"id":21807291,"url":"https://github.com/pertsevds/predicate_dispatch","last_synced_at":"2026-02-11T06:02:27.013Z","repository":{"id":62710127,"uuid":"561932167","full_name":"pertsevds/predicate_dispatch","owner":"pertsevds","description":"Predicative dispatch decorator for Python, based on idea from book \"Functional Programming in Python\"","archived":false,"fork":false,"pushed_at":"2022-12-23T05:59:20.000Z","size":87,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-24T00:24:09.885Z","etag":null,"topics":["dispatch","functional-programming","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pertsevds.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-11-04T20:37:36.000Z","updated_at":"2025-04-17T21:40:57.000Z","dependencies_parsed_at":"2023-01-30T17:45:18.217Z","dependency_job_id":null,"html_url":"https://github.com/pertsevds/predicate_dispatch","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/pertsevds/predicate_dispatch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pertsevds%2Fpredicate_dispatch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pertsevds%2Fpredicate_dispatch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pertsevds%2Fpredicate_dispatch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pertsevds%2Fpredicate_dispatch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pertsevds","download_url":"https://codeload.github.com/pertsevds/predicate_dispatch/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pertsevds%2Fpredicate_dispatch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29327848,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-11T03:52:29.695Z","status":"ssl_error","status_checked_at":"2026-02-11T03:52:23.094Z","response_time":97,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dispatch","functional-programming","python"],"created_at":"2024-11-27T12:39:10.682Z","updated_at":"2026-02-11T06:02:26.983Z","avatar_url":"https://github.com/pertsevds.png","language":"Python","readme":"# Predicate_dispatch\n\n![Github Actions](https://github.com/pdm-project/pdm/workflows/Tests/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/pertsevds/predicate_dispatch/badge.svg?branch=main)](https://coveralls.io/github/pertsevds/predicate_dispatch?branch=main)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![pdm-managed](https://img.shields.io/badge/pdm-managed-blueviolet)](https://pdm.fming.dev)\n\nPredicative dispatch decorator for Python, based on the idea from [Functional Programming in Python](http://www.oreilly.com/programming/free/functional-programming-python.csp).\n\nThe module is providing means to specify conditions with a lambda function that determines which function is called.\nThe number of arguments in the condition function in the `@predicate` decorator must be equal to the number of arguments of the wrapped function.\n\n## Installation\n\nPredicate_dispatch requires Python 3.7 or higher.\n```\npip install predicate_dispatch\n```\n\n## Basic usage\n\n```python\nfrom predicate_dispatch import predicate\n\n@predicate(lambda x: x \u003e 1)\ndef factorial(x):\n  return x * factorial(x - 1)\n\n@predicate()\ndef factorial(x):\n  return x\n        \nfactorial(5) == 120\n```\n\n`@predicate()` - is the default predicate. It is used when none of the other predicates resolves to True.\n\n## Caching\n\n### Types of cache in predicate_dispatch functions\n\n| Decorator name | Cache type |\n| ----------- | ----------- |\n| `predicate` | Without cache |\n| `predicate_cache` | Function choice is cached |\n| `predicate_cache_result` | Function result is cached |\n\n### `predicate` - without cache\n\nYou must use the `predicate` decorator if the result of the lambda function in the predicate for the same argument `x` changes over time. For example, if you compare `x` to the current time or execution count.\n\nIf you don't want to dig deeper into the quirks of caching just use the `predicate` decorator.\n\nFor example:\n\n```python\ndef get_events(x):\n    if x \u003e= time.time():\n        return database.getFutureEvents()\n    if x \u003c time.time():\n        return database.getPastEvents()\n    return []\n```\n\nTo this:\n\n```python\n@predicate(lambda x: x \u003e= time.time())\ndef get_events(x):\n    return database.getFutureEvents()\n\n@predicate(lambda x: x \u003c time.time())\ndef get_events(x):\n    return database.getPastEvents()\n\n@predicate()\ndef get_events(x):\n    return []\n```\n\n### `predicate_cache` - function choice is cached\n\nYou may use the `predicate_cache` decorator if the result of the lambda function in the predicate for the same argument `x` does not change over time, but the result from calling the real function will change. This decorator will cache what function was called previously for certain `x`. For example, if you have code like this:\n\n```python\ndef get_logs(x):\n    if x == 1:\n        return database.getLogsForDog()\n    if x == 2:\n        return database.getLogsForCat()\n    if x == 3:\n        return database.getLogsForFox()\n    return database.getLogsForOtherAnimal()\n```\n\nYou may rewrite it to the `predicate_cache` decorator like this:\n\n```python\n@predicate_cache(lambda x: x == 1)\ndef get_logs(x):\n    return database.getLogsForDog()\n\n@predicate_cache(lambda x: x == 2)\ndef get_logs(x):\n    return database.getLogsForCat()\n\n@predicate_cache(lambda x: x == 3)\ndef get_logs(x):\n    return database.getLogsForFox()\n\n@predicate_cache()\ndef get_logs(x):\n    return database.getLogsForOtherAnimal()\n```\n\nWhen you first call `get_logs(3)` internally it will compare `3` to `1`, then `3` to `2`, then `3` to `3` and execute `db.getLogsForFox()`. When you call `get_logs(3)` again it will take the previous function choice from the cache and straightaway execute `db.getLogsForFox()`.\n\n### `predicate_cache_result` - function result is cached\n\nYou may use the `predicate_cache_result` decorator if the result of the lambda function in the predicate for the same argument `x` does not change over time and the result from calling the real function does not change over time. This decorator will cache the previous result of calling the function with a certain `x`. A typical example would be when you want to use `predicate_dispatch` instead of many static ifs.\n\nFrom this:\n\n```python\ndef get_animal(x):\n    if x == 1:\n        return \"dog\"\n    if x == 2:\n        return \"cat\"\n    if x == 3:\n        return \"fox\"\n    return \"animal\"\n```\n\nTo this:\n\n```python\n@predicate_cache_result(lambda x: x == 1)\ndef get_animal(x):\n    return \"dog\"\n\n@predicate_cache_result(lambda x: x == 2)\ndef get_animal(x):\n    return \"cat\"\n\n@predicate_cache_result(lambda x: x == 3)\ndef get_animal(x):\n    return \"fox\"\n\n@predicate_cache_result()\ndef get_animal(x):\n    return \"animal\"\n```\n\nWhen you first call `get_animal(3)` internally it will compare `3` to `1`, then `3` to `2`, then `3` to `3` and then return result `\"fox\"`. When you call `get_animal(3)` again it will take the previous result from the cache and return it.\n\n\n## Limitations\n\n- The number of arguments in the condition function in the `@predicate` or `@predicate_cache` or `@predicate_cache_result` decorator must be equal to the number of arguments of the wrapped function.\n- Only one function as an argument in the predicate.\n- Only the last default predicate will be executed.\n\n## License\n\n```\nCopyright 2015 Juraj Sebin \u003csebin.juraj@gmail.com\u003e\nCopyright 2022 Dmitriy Pertsev \u003cdavaeron@gmail.com\u003e\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n\n## Original project\n- [pypd by Juraj Sebin](https://github.com/septumca/pypd)\n\n## Similar projects\n\n- [plum](https://github.com/wesselb/plum)\n- [multipledispatch](https://github.com/mrocklin/multipledispatch)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpertsevds%2Fpredicate_dispatch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpertsevds%2Fpredicate_dispatch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpertsevds%2Fpredicate_dispatch/lists"}