lazy_core Module

Core classes module

Summary of module contents:

Name Description
OpMethod Internal class to represent an operator method metadata.
AbstractOperatorOverloaderMeta Abstract metaclass for classes with massively overloaded operators.
MultiKeyDict Multiple keys dict.
StrategyDict Strategy dictionary manager creator with default, mainly done for callables and multiple implementation algorithms / models.
class OpMethod[source]

Bases: object

Internal class to represent an operator method metadata.

You can acess operator methods directly by using the OpMethod.get() class method, which always returns a generator from a query. This might be helpful if you need to acess the operator module from symbols. Given an instance “op”, it has the following data:

Attribute Contents (and an example with OpMethod.get(“__radd__”))
op.name Operator name string, e.g. "radd".
op.dname Dunder name string, e.g. "__radd__".
op.func Function reference, e.g. operator.__add__.
op.symbol Operator symbol if in a code as a string, e.g. "+".
op.rev Boolean telling if the operator is reversed, e.g. True.
op.arity Number of operands, e.g. 2.

See the OpMethod.get docstring for more information and examples.

__repr__()[source]
_all = {1: [<pos operator method ('+' symbol)>, <neg operator method ('-' symbol)>, <invert operator method ('~' symbol)>], 2: [<add operator method ('+' symbol)>, <radd operator method ('+' symbol)>, <sub operator method ('-' symbol)>, <rsub operator method ('-' symbol)>, <mul operator method ('*' symbol)>, <rmul operator method ('*' symbol)>, <truediv operator method ('/' symbol)>, <rtruediv operator method ('/' symbol)>, <floordiv operator method ('//' symbol)>, <rfloordiv operator method ('//' symbol)>, <mod operator method ('%' symbol)>, <rmod operator method ('%' symbol)>, <pow operator method ('**' symbol)>, <rpow operator method ('**' symbol)>, <rshift operator method ('>>' symbol)>, <rrshift operator method ('>>' symbol)>, <lshift operator method ('<<' symbol)>, <rlshift operator method ('<<' symbol)>, <and operator method ('&' symbol)>, <rand operator method ('&' symbol)>, <or operator method ('|' symbol)>, <ror operator method ('|' symbol)>, <xor operator method ('^' symbol)>, <rxor operator method ('^' symbol)>, <lt operator method ('<' symbol)>, <le operator method ('<=' symbol)>, <eq operator method ('==' symbol)>, <ne operator method ('!=' symbol)>, <gt operator method ('>' symbol)>, <ge operator method ('>=' symbol)>, <matmul operator method ('@' symbol)>, <rmatmul operator method ('@' symbol)>], 'xor': [<xor operator method ('^' symbol)>], 'rlshift': [<rlshift operator method ('<<' symbol)>], '__neg__': [<neg operator method ('-' symbol)>], <built-in function xor>: [<xor operator method ('^' symbol)>, <rxor operator method ('^' symbol)>], '__rmod__': [<rmod operator method ('%' symbol)>], '__radd__': [<radd operator method ('+' symbol)>], '__rsub__': [<rsub operator method ('-' symbol)>], '+': [<add operator method ('+' symbol)>, <radd operator method ('+' symbol)>, <pos operator method ('+' symbol)>], '^': [<xor operator method ('^' symbol)>, <rxor operator method ('^' symbol)>], '**': [<pow operator method ('**' symbol)>, <rpow operator method ('**' symbol)>], '//': [<floordiv operator method ('//' symbol)>, <rfloordiv operator method ('//' symbol)>], 'all': [<add operator method ('+' symbol)>, <radd operator method ('+' symbol)>, <pos operator method ('+' symbol)>, <sub operator method ('-' symbol)>, <rsub operator method ('-' symbol)>, <neg operator method ('-' symbol)>, <mul operator method ('*' symbol)>, <rmul operator method ('*' symbol)>, <truediv operator method ('/' symbol)>, <rtruediv operator method ('/' symbol)>, <floordiv operator method ('//' symbol)>, <rfloordiv operator method ('//' symbol)>, <mod operator method ('%' symbol)>, <rmod operator method ('%' symbol)>, <pow operator method ('**' symbol)>, <rpow operator method ('**' symbol)>, <rshift operator method ('>>' symbol)>, <rrshift operator method ('>>' symbol)>, <lshift operator method ('<<' symbol)>, <rlshift operator method ('<<' symbol)>, <invert operator method ('~' symbol)>, <and operator method ('&' symbol)>, <rand operator method ('&' symbol)>, <or operator method ('|' symbol)>, <ror operator method ('|' symbol)>, <xor operator method ('^' symbol)>, <rxor operator method ('^' symbol)>, <lt operator method ('<' symbol)>, <le operator method ('<=' symbol)>, <eq operator method ('==' symbol)>, <ne operator method ('!=' symbol)>, <gt operator method ('>' symbol)>, <ge operator method ('>=' symbol)>, <matmul operator method ('@' symbol)>, <rmatmul operator method ('@' symbol)>], <built-in function lt>: [<lt operator method ('<' symbol)>], 'pos': [<pos operator method ('+' symbol)>], 'rmatmul': [<rmatmul operator method ('@' symbol)>], <built-in function le>: [<le operator method ('<=' symbol)>], 'and': [<and operator method ('&' symbol)>], '__eq__': [<eq operator method ('==' symbol)>], 'rmul': [<rmul operator method ('*' symbol)>], 'rshift': [<rshift operator method ('>>' symbol)>], 'rfloordiv': [<rfloordiv operator method ('//' symbol)>], '__pos__': [<pos operator method ('+' symbol)>], '__ge__': [<ge operator method ('>=' symbol)>], '@': [<matmul operator method ('@' symbol)>, <rmatmul operator method ('@' symbol)>], 'r': [<radd operator method ('+' symbol)>, <rsub operator method ('-' symbol)>, <rmul operator method ('*' symbol)>, <rtruediv operator method ('/' symbol)>, <rfloordiv operator method ('//' symbol)>, <rmod operator method ('%' symbol)>, <rpow operator method ('**' symbol)>, <rrshift operator method ('>>' symbol)>, <rlshift operator method ('<<' symbol)>, <rand operator method ('&' symbol)>, <ror operator method ('|' symbol)>, <rxor operator method ('^' symbol)>, <rmatmul operator method ('@' symbol)>], 'truediv': [<truediv operator method ('/' symbol)>], '__lt__': [<lt operator method ('<' symbol)>], '/': [<truediv operator method ('/' symbol)>, <rtruediv operator method ('/' symbol)>], <built-in function pow>: [<pow operator method ('**' symbol)>, <rpow operator method ('**' symbol)>], 'invert': [<invert operator method ('~' symbol)>], 'eq': [<eq operator method ('==' symbol)>], '__rmatmul__': [<rmatmul operator method ('@' symbol)>], 'gt': [<gt operator method ('>' symbol)>], '__rlshift__': [<rlshift operator method ('<<' symbol)>], '__pow__': [<pow operator method ('**' symbol)>], '__lshift__': [<lshift operator method ('<<' symbol)>], '__gt__': [<gt operator method ('>' symbol)>], 'lt': [<lt operator method ('<' symbol)>], 'rmod': [<rmod operator method ('%' symbol)>], '<<': [<lshift operator method ('<<' symbol)>, <rlshift operator method ('<<' symbol)>], 'le': [<le operator method ('<=' symbol)>], '__rpow__': [<rpow operator method ('**' symbol)>], '|': [<or operator method ('|' symbol)>, <ror operator method ('|' symbol)>], '1': [<pos operator method ('+' symbol)>, <neg operator method ('-' symbol)>, <invert operator method ('~' symbol)>], <built-in function mod>: [<mod operator method ('%' symbol)>, <rmod operator method ('%' symbol)>], 'radd': [<radd operator method ('+' symbol)>], '__rand__': [<rand operator method ('&' symbol)>], '__invert__': [<invert operator method ('~' symbol)>], <built-in function lshift>: [<lshift operator method ('<<' symbol)>, <rlshift operator method ('<<' symbol)>], <built-in function matmul>: [<matmul operator method ('@' symbol)>, <rmatmul operator method ('@' symbol)>], '~': [<invert operator method ('~' symbol)>], <built-in function rshift>: [<rshift operator method ('>>' symbol)>, <rrshift operator method ('>>' symbol)>], 'rrshift': [<rrshift operator method ('>>' symbol)>], '__mul__': [<mul operator method ('*' symbol)>], '__ne__': [<ne operator method ('!=' symbol)>], <built-in function neg>: [<neg operator method ('-' symbol)>], <built-in function gt>: [<gt operator method ('>' symbol)>], 'neg': [<neg operator method ('-' symbol)>], '__mod__': [<mod operator method ('%' symbol)>], 'rand': [<rand operator method ('&' symbol)>], '-': [<sub operator method ('-' symbol)>, <rsub operator method ('-' symbol)>, <neg operator method ('-' symbol)>], <built-in function pos>: [<pos operator method ('+' symbol)>], '__truediv__': [<truediv operator method ('/' symbol)>], <built-in function invert>: [<invert operator method ('~' symbol)>], 'ge': [<ge operator method ('>=' symbol)>], 'ne': [<ne operator method ('!=' symbol)>], 'add': [<add operator method ('+' symbol)>], '==': [<eq operator method ('==' symbol)>], '__xor__': [<xor operator method ('^' symbol)>], 'pow': [<pow operator method ('**' symbol)>], 'rsub': [<rsub operator method ('-' symbol)>], 'rxor': [<rxor operator method ('^' symbol)>], '<': [<lt operator method ('<' symbol)>], <built-in function and_>: [<and operator method ('&' symbol)>, <rand operator method ('&' symbol)>], 'matmul': [<matmul operator method ('@' symbol)>], 'ror': [<ror operator method ('|' symbol)>], 'sub': [<sub operator method ('-' symbol)>], '>=': [<ge operator method ('>=' symbol)>], '__floordiv__': [<floordiv operator method ('//' symbol)>], '__le__': [<le operator method ('<=' symbol)>], '>': [<gt operator method ('>' symbol)>], <built-in function or_>: [<or operator method ('|' symbol)>, <ror operator method ('|' symbol)>], '&': [<and operator method ('&' symbol)>, <rand operator method ('&' symbol)>], '__rtruediv__': [<rtruediv operator method ('/' symbol)>], '!=': [<ne operator method ('!=' symbol)>], <built-in function ge>: [<ge operator method ('>=' symbol)>], '__ror__': [<ror operator method ('|' symbol)>], '__rfloordiv__': [<rfloordiv operator method ('//' symbol)>], <built-in function add>: [<add operator method ('+' symbol)>, <radd operator method ('+' symbol)>], '__rmul__': [<rmul operator method ('*' symbol)>], '__rrshift__': [<rrshift operator method ('>>' symbol)>], '__rxor__': [<rxor operator method ('^' symbol)>], '__matmul__': [<matmul operator method ('@' symbol)>], 'mul': [<mul operator method ('*' symbol)>], <built-in function eq>: [<eq operator method ('==' symbol)>], '<=': [<le operator method ('<=' symbol)>], 'floordiv': [<floordiv operator method ('//' symbol)>], 'rpow': [<rpow operator method ('**' symbol)>], <built-in function ne>: [<ne operator method ('!=' symbol)>], '__sub__': [<sub operator method ('-' symbol)>], '%': [<mod operator method ('%' symbol)>, <rmod operator method ('%' symbol)>], <built-in function floordiv>: [<floordiv operator method ('//' symbol)>, <rfloordiv operator method ('//' symbol)>], '__or__': [<or operator method ('|' symbol)>], 'mod': [<mod operator method ('%' symbol)>], 'or': [<or operator method ('|' symbol)>], 'lshift': [<lshift operator method ('<<' symbol)>], <built-in function truediv>: [<truediv operator method ('/' symbol)>, <rtruediv operator method ('/' symbol)>], '__rshift__': [<rshift operator method ('>>' symbol)>], <built-in function sub>: [<sub operator method ('-' symbol)>, <rsub operator method ('-' symbol)>], '>>': [<rshift operator method ('>>' symbol)>, <rrshift operator method ('>>' symbol)>], '__add__': [<add operator method ('+' symbol)>], <built-in function mul>: [<mul operator method ('*' symbol)>, <rmul operator method ('*' symbol)>], 'rtruediv': [<rtruediv operator method ('/' symbol)>], '__and__': [<and operator method ('&' symbol)>], '*': [<mul operator method ('*' symbol)>, <rmul operator method ('*' symbol)>], '2': [<add operator method ('+' symbol)>, <radd operator method ('+' symbol)>, <sub operator method ('-' symbol)>, <rsub operator method ('-' symbol)>, <mul operator method ('*' symbol)>, <rmul operator method ('*' symbol)>, <truediv operator method ('/' symbol)>, <rtruediv operator method ('/' symbol)>, <floordiv operator method ('//' symbol)>, <rfloordiv operator method ('//' symbol)>, <mod operator method ('%' symbol)>, <rmod operator method ('%' symbol)>, <pow operator method ('**' symbol)>, <rpow operator method ('**' symbol)>, <rshift operator method ('>>' symbol)>, <rrshift operator method ('>>' symbol)>, <lshift operator method ('<<' symbol)>, <rlshift operator method ('<<' symbol)>, <and operator method ('&' symbol)>, <rand operator method ('&' symbol)>, <or operator method ('|' symbol)>, <ror operator method ('|' symbol)>, <xor operator method ('^' symbol)>, <rxor operator method ('^' symbol)>, <lt operator method ('<' symbol)>, <le operator method ('<=' symbol)>, <eq operator method ('==' symbol)>, <ne operator method ('!=' symbol)>, <gt operator method ('>' symbol)>, <ge operator method ('>=' symbol)>, <matmul operator method ('@' symbol)>, <rmatmul operator method ('@' symbol)>]}
classmethod _initialize()[source]

Internal method to initialize the class by creating all the operator metadata to be used afterwards.

classmethod _insert(name, symbol)[source]
classmethod get(key='all', without=None)[source]
class AbstractOperatorOverloaderMeta[source]

Bases: abc.ABCMeta

Abstract metaclass for classes with massively overloaded operators.

Dunders dont’t appear within “getattr” nor “getattribute”, and they should be inside the class dictionary, not the class instance one, otherwise they won’t be found by the usual mechanism. That’s why we have to be eager here. You need a concrete class inherited from this one, and the “abstract” enforcement and specification is:

  • Override __operators__ and __without__ with a OpMethod.get() valid query inputs, see that method docstring for more information and examples. Its a good idea to tell all operators that will be used, including the ones that should be defined in the instance namespace, since the metaclass will enforce their existance without overwriting.

    These should be overridden by a string or a list with all operator names, symbols or operator functions (from the operator module) to be overloaded (or neglect, in the __without__).

    • When using names, reversed operators should be given explicitly.
    • When using symbols the reversed operators and the unary are implicit.
    • When using operator functions, the ooperators and the unary are implicit.

    By default, __operators__ is “all” and __without__ is None.

  • All operators should be implemented by the metaclass hierarchy or by the class directly, and the class has priority when both exists, neglecting the method builder in this case.

  • There are three method builders which should be written in the concrete metaclass: __binary__, __rbinary__ and __unary__. All receives 2 parameters (the class being instantiated and a OpMethod instance) and should return a function for the specific dunder, probably doing so based on general-use templates.

Note

Don’t use “div”! In Python 2.x it’ll be a copy of truediv.

__binary__(op)[source]

This method should be overridden to return the dunder for the given operator function.

static __new__(mcls, name, bases, namespace)[source]
__operators__ = 'all'
__rbinary__(op)

This method should be overridden to return the dunder for the given operator function.

__unary__(op)

This method should be overridden to return the dunder for the given operator function.

__without__ = None
class MultiKeyDict(*args, **kwargs)[source]

Bases: dict

Multiple keys dict.

Can be thought as an “inversible” dict where you can ask for the one hashable value from one of the keys. By default it iterates through the values, if you need an iterator for all tuples of keys, use iterkeys method instead.

Examples:

Assignments one by one:

>>> mk = MultiKeyDict()
>>> mk[1] = 3
>>> mk[2] = 3
>>> mk
{(1, 2): 3}
>>> mk[4] = 2
>>> mk[1] = 2
>>> len(mk)
2
>>> mk[1]
2
>>> mk[2]
3
>>> mk[4]
2
>>> sorted(mk)
[2, 3]
>>> sorted(mk.keys())
[(2,), (4, 1)]

Casting from another dict:

>>> mkd = MultiKeyDict({1:4, 2:5, -7:4})
>>> len(mkd)
2
>>> sorted(mkd)
[4, 5]
>>> del mkd[2]
>>> len(mkd)
1
>>> sorted(list(mkd.keys())[0]) # Sorts the only key tuple
[-7, 1]
>>> del mkd[-7]
>>> len(mkd) # Again, that's the amount of values, not of keys!
1
__delitem__(key)[source]
__getitem__(key)[source]
__init__(*args, **kwargs)[source]
__iter__()[source]
__setitem__(key, value)[source]
key2keys(key)[source]

Tuple with every key that points to the same value.

value2keys(value)[source]

Tuple with every key that points to the given value. Result might be empty.

class StrategyDict(*args, **kwargs)[source]

Bases: audiolazy.lazy_core.MultiKeyDict

Strategy dictionary manager creator with default, mainly done for callables and multiple implementation algorithms / models.

Each strategy might have multiple names. The names can be any hashable. The “strategy” method creates a decorator for the given strategy names, see its docstrings for more details on this.

The default strategy is the attribute StrategyDict.default, and might be anything from outside the dictionary values. The default strategy is the first strategy you insert, unless the instance attribute already exists.

The instances iterates through its values (i.e., for each strategy, not its names). You can type something like this to find all StrategyDict instances from the package:

.. code-block:: python

import audiolazy sorted(k for k, v in vars(audiolazy).items()

if isinstance(v, audiolazy.StrategyDict))
Examples:
>>> sd = StrategyDict()
>>> @sd.strategy("sum") # First strategy is default
... def sd(a, b, c):
...     return a + b + c
>>> @sd.strategy("min", "m") # Multiple names
... def sd(a, b, c):
...     return min(a, b, c)
>>> sd(2, 5, 0)
7
>>> sd["min"](2, 5, 0)
0
>>> sd["m"](7, -5, -2)
-5
>>> sd.default = sd["min"]
>>> sd(-19, 1e18, 0)
-19

Note

The StrategyDict constructor creates a new class inheriting from StrategyDict, and then instantiates it before returning the requested instance. This singleton subclassing is needed for docstring personalization.

__call__(*args, **kwargs)[source]
__delattr__(attr)[source]
__delitem__(key)[source]
__iter__()[source]
static __new__(name='strategy_dict_unnamed_instance')[source]

Creates a new StrategyDict class and returns an instance of it. The new class is needed to ensure it’ll have a personalized docstring.

__setitem__(key, value)[source]
default(*args, **kwargs)
strategy(*names, **kwargs)[source]

StrategyDict wrapping method for adding a new strategy.

Parameters:
  • *names

    Positional arguments with all names (strings) that could be used to call the strategy to be added, to be used both as key items and as attribute names.

  • keep_name – Boolean keyword-only parameter for choosing whether the __name__ attribute of the decorated/wrapped function should be changed or kept. Defaults to False (i.e., changes the name by default).
Returns:

A decorator/wrapper function to be used once on the new strategy to be added.

Let’s create a StrategyDict that knows its name:

>>> txt_proc = StrategyDict("txt_proc")

Add a first strategy swapcase, using this method as a decorator factory:

>>> @txt_proc.strategy("swapcase")
... def txt_proc(txt):
...   return txt.swapcase()

Let’s do it again, but wrapping the strategy functions inline. First two strategies have multiple names, the last keeps the function name, which would otherwise be replaced by the first given name:

>>> txt_proc.strategy("lower", "low")(lambda txt: txt.lower())
{(...): <function ... at 0x...>, (...): <function ... at 0x...>}
>>> txt_proc.strategy("upper", "up")(lambda txt: txt.upper())
{...}
>>> txt_proc.strategy("keep", keep_name=True)(lambda txt: txt)
{...}

We can now iterate through the strategies to call them or see their function names

>>> sorted(st("Just a Test") for st in txt_proc)
['JUST A TEST', 'Just a Test', 'jUST A tEST', 'just a test']
>>> sorted(st.__name__ for st in txt_proc) # Just the first name
['<lambda>', 'lower', 'swapcase', 'upper']

Calling a single strategy:

>>> txt_proc.low("TeStInG")
'testing'
>>> txt_proc["upper"]("TeStInG")
'TESTING'
>>> txt_proc("TeStInG") # Default is the first: swapcase
'tEsTiNg'
>>> txt_proc.default("TeStInG")
'tEsTiNg'
>>> txt_proc.default = txt_proc.up # Manually changing the default
>>> txt_proc("TeStInG")
'TESTING'

Hint

Default strategy is the one stored as the default attribute, you can change or remove it at any time. When removing all keys that are assigned to the default strategy, the default attribute will be removed from the StrategyDict instance as well. The first strategy added afterwards is the one that will become the new default, unless the attribute is created or changed manually.