Make any type binary-combinable with a single line of code.
Project description
Make any type binary-combinable with a single line of code.
The most obvious use case arguably is the creation of binary expressions over custom types, but bincombo is not limited to combination of boolean values. By providing appropriate map/reduce operations, any type of data of the discrete members of a combination can be aggregated to form a combined result.
The implementation solely relies on inheritance, no meta programming is involved. You are free to use your own metaclasses, should you wish to do so.
Suppose you have a custom type Check, which accepts or rejects values depending on the result of the invocation of some callable. You can make instances of it combinable using the binary operators & (and) and | (or) and also support the unary ~ (invert) by using the combinable() decorator:
import bincombo @bincombo.combinable(methods=("check",)) class Check: __slots__ = ("checker",) def __init__(self, checker): self.checker = checker def check(self, value): return self.checker(value)
Now, Check objects can be binary-combined:
c1 = Check(lambda v: isinstance(v, int) and v >= 42) c2 = Check(lambda v: isinstance(v, str)) c3 = Check(lambda v: "hello" in v) c = c1 | c2 & ~c3 c.check(41) # False c.check(42) # True c.check("hello, world!") # False c.check("hey, world!") # True
The combinable() decorator creates a number of types needed to represent discrete checks and combinations thereof. These are stored in a Config object, which is aavailable as class attribute BIN_CONFIG of Check. It can be worth storing these types as module attributes alongside your Check class to have them at hand for explicit use or type checking:
BaseCheck = Check.BIN_CONFIG.base_type CheckCombo = Check.BIN_CONFIG.combo_type AllChecks = Check.BIN_CONFIG.and_type AnyCheck = Check.BIN_CONFIG.or_type
All types in this module have __slots__ defined for smaller memory footprints and improved lookup times, as have the types created by combinable(). It is recommended to also equip your own type with __slots__ if possible to benefit from entirely __dict__-less objects.
To gain a better understanding of how all the types relate or to further customize them, here is how you would make Check binary-combinable without using the combinable() helper:
# This is a base class from which both the discrete Check type and the type # representing a combination of Check objects will inherit. # It can be used, for instance, to test whether some object is Check-like # using isinstance(obj, BaseCheck). class BaseCheck: __slots__ = () # Check should support all three operations. feature_mixins = ( bincombo.AndSupportMixin, bincombo.OrSupportMixin, bincombo.InvertSupportMixin ) # This is the type that would normally be returned by combinable() decorator. # Here it replaces the original Check, but you could also give it a different name. class Check(*feature_mixins, Check, BaseCheck): __slots__ = () # Objects of this type represent (possibly negated) AND/OR combinations of # Check objects. class CheckCombo(*feature_mixins, bincombo.Combo, BaseCheck): __slots__ = () # Create a proxy check() method that queries an individual combo member. # bincombo will call this method for all members, combining the returned # boolean values using and/or, depending on the combination type, and possibly # invert the final result. @bincombo.combine_members def check(self, member, value): return member.check(value) # This is an AND combination. class AllChecks(bincombo.AndComboMixin, CheckCombo): __slots__ = () # This is an OR combination. class AnyCheck(bincombo.OrComboMixin, CheckCombo): __slots__ = () # Finally, bincombo has to be taught all the types just created. # By attaching the Config object to BaseCheck as a class attribute, both Check # and CheckCombo instances will have it available due to inheritance. BaseCheck.BIN_CONFIG = bincombo.Config( BaseCheck, Check, CheckCombo, AllChecks, AnyCheck )
Further customization of the combining abilities is possible, the documentations of combinable(), combine_members() and Config have more information.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file bincombo-0.1.0.tar.gz
.
File metadata
- Download URL: bincombo-0.1.0.tar.gz
- Upload date:
- Size: 8.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.1.14 CPython/3.7.3 Linux/5.10.0-0.bpo.15-amd64
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7a870afd86f9d646c70117c60f064530498af7b264b7983539623865678a6cd0 |
|
MD5 | c6d3298165d999665fb3ad3701fb8f44 |
|
BLAKE2b-256 | 6cb47d4764f611eaeeafc31c2ec59301c6b60916b9b5b32af047a762de70e543 |
File details
Details for the file bincombo-0.1.0-py3-none-any.whl
.
File metadata
- Download URL: bincombo-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.1.14 CPython/3.7.3 Linux/5.10.0-0.bpo.15-amd64
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4cce5f67ef512f81f57fbe2c8315167793548460f5e9a74dd3a6c23e1e951fb9 |
|
MD5 | 49221b506b0a1cc1903c50c4ae35ea32 |
|
BLAKE2b-256 | e321c366c441094c37f2400df61b040f6e8f004651e53a6d9094d36c0e76198c |