Skip to content

Reference

At the core of lazyfunc is the LazyFunc class. It makes operations between callables and arbitrary datatypes possible, by deferring evaluation to a later time.

The methods and properties of the LazyFunc class are listed below.

LazyFunc

Operations between callables, with lazy evaluation.

Source code in lazyfunc/lazy_func.py
class LazyFunc(metaclass=LazyFuncMeta):
    """Operations between callables, with lazy evaluation."""

    def __init__(self, func, description=None, **kwargs):
        self.func = func
        self._description = description
        self._kwargs = self._default_kwargs = kwargs
        self._precedence = None

    @property
    def __signature__(self):
        return inspect.signature(self.func)

    @property
    def description(self) -> str:
        """Defaults to the name of the wrapped callable, but can be set by the user at
        object initialisation. Also updated when operations are applied with other
        callables.

        Examples:
            >>> def my_function(x):
            ...     return x
            >>> lf_auto = LazyFunc(my_function)
            >>> lf_auto.description
            'my_function'
            >>> lf_named = LazyFunc(my_function, description='my_named_function')
            >>> lf_named.description
            'my_named_function'

        Returns:
            A string describing the wrapped function.
        """
        if self._description is None:
            return callable_name(self.func)
        else:
            return self._description

    @property
    def __name__(self) -> str:
        """Alias of the LazyFunc description."""
        return self.description

    def __repr__(self):
        return f"{self.__class__.__name__}({self.description})"

    def __call__(self, *args, **kwargs) -> object:
        """Either calls the wrapped function with the provided args and kwargs, or if
        the first argument is a callable, returns a new LazyFunc object of
        LazyFunc(args[0](self)).

        When calling a LazyFunc instance, if the first argument is NOT a callable, it
        behaves exactly as the unwrapped callable.

        Examples:
            >>> @LazyFunc
            ... def my_function(x):
            ...     return 2 * x
            ...
            >>> my_function('foo')  # first argument is not callable
            'foofoo'
            >>> import builtins
            >>> builtin_min = builtins.min
            >>> min = LazyFunc(min)
            >>> min([3, 1, 4, 1, 5, 9])  # first argument is not callable
            1
            >>> min('lazy', 'function', key=lambda s: s[1])  # first argument is
            ...                                              # not callable
            'lazy'
            >>> min_of_my_function = min(my_function)  # first argument is callable
            >>> min_of_my_function
            LazyFunc(min(my_function))

        Args:
            args: Positional arguments to be passed to wrapped function.
            kwargs: Keyword arguments to be passed to wrapped function.

        Returns: Either the result of the wrapped function evaluated with the
        supplied args and _kwargs, or a new LazyFunc instance.
        """
        if callable(args[0]):
            operator_precedence = 17
            other_func, *args = args

            def new_func(*x):
                return self.func(other_func(*x), *args, **kwargs)

            new_desc = (
                LazyFuncMeta._get_desc(self, operator_precedence)
                + "("
                + callable_name(other_func)
                + ")"
            )
            mf = LazyFunc(func=new_func, description=new_desc)
            mf._precedence = operator_precedence
            return mf
        else:  # when the function is called the kwargs supplied to the call take
            # precedence over those set elsewhere
            final_kwargs = self._kwargs | kwargs
            return self.func(*args, **final_kwargs)

    def set_kwargs(self, **kwargs):
        self._kwargs = kwargs
        return self

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self._kwargs = self._default_kwargs

    def is_equal(self, other: callable) -> bool:
        """Checks for equality between self and other.

        To stay consistent with LazyFunc's other dunder methods, the `__eq__` method
        lazily compares equality between the wrapped LazyFunc and other. Therefore,
        this method exists to check whether two unevaluated LazyFunc objects are
        equal, without calling them and comparing the results.

        Examples:
            >>> def my_function(x):
            ...     return x
            >>> lf_auto_1 = LazyFunc(my_function)
            >>> lf_auto_2 = LazyFunc(my_function)
            >>> lf_named = LazyFunc(my_function, description='my_named_function')
            >>> lf_auto_1.is_equal(lf_auto_2)
            True
            >>> lf_auto_1.is_equal(lf_named)
            False
        """
        try:
            equal = self.description == other.description
        except AttributeError:
            msg = "Can only compare a LazyFunc instance with another LazyFunc"
            raise TypeError(msg)

        if not equal:
            msg = (
                "LazyFunc descriptions found to be not equal though may still be "
                "equivalent. "
            )
            warn(msg)

        return equal

description: str property readonly

Defaults to the name of the wrapped callable, but can be set by the user at object initialisation. Also updated when operations are applied with other callables.

Examples:

>>> def my_function(x):
...     return x
>>> lf_auto = LazyFunc(my_function)
>>> lf_auto.description
'my_function'
>>> lf_named = LazyFunc(my_function, description='my_named_function')
>>> lf_named.description
'my_named_function'

Returns:

Type Description
str

A string describing the wrapped function.

__add__(*instances) special

Return new instance LazyFunc(self + other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__and__(*instances) special

Return new instance LazyFunc(self & other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__call__(self, *args, **kwargs) special

Either calls the wrapped function with the provided args and kwargs, or if the first argument is a callable, returns a new LazyFunc object of LazyFunc(args0).

When calling a LazyFunc instance, if the first argument is NOT a callable, it behaves exactly as the unwrapped callable.

Examples:

>>> @LazyFunc
... def my_function(x):
...     return 2 * x
...
>>> my_function('foo')  # first argument is not callable
'foofoo'
>>> import builtins
>>> builtin_min = builtins.min
>>> min = LazyFunc(min)
>>> min([3, 1, 4, 1, 5, 9])  # first argument is not callable
1
>>> min('lazy', 'function', key=lambda s: s[1])  # first argument is
...                                              # not callable
'lazy'
>>> min_of_my_function = min(my_function)  # first argument is callable
>>> min_of_my_function
LazyFunc(min(my_function))

Parameters:

Name Type Description Default
args

Positional arguments to be passed to wrapped function.

()
kwargs

Keyword arguments to be passed to wrapped function.

{}

Returns: Either the result of the wrapped function evaluated with the supplied args and _kwargs, or a new LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def __call__(self, *args, **kwargs) -> object:
    """Either calls the wrapped function with the provided args and kwargs, or if
    the first argument is a callable, returns a new LazyFunc object of
    LazyFunc(args[0](self)).

    When calling a LazyFunc instance, if the first argument is NOT a callable, it
    behaves exactly as the unwrapped callable.

    Examples:
        >>> @LazyFunc
        ... def my_function(x):
        ...     return 2 * x
        ...
        >>> my_function('foo')  # first argument is not callable
        'foofoo'
        >>> import builtins
        >>> builtin_min = builtins.min
        >>> min = LazyFunc(min)
        >>> min([3, 1, 4, 1, 5, 9])  # first argument is not callable
        1
        >>> min('lazy', 'function', key=lambda s: s[1])  # first argument is
        ...                                              # not callable
        'lazy'
        >>> min_of_my_function = min(my_function)  # first argument is callable
        >>> min_of_my_function
        LazyFunc(min(my_function))

    Args:
        args: Positional arguments to be passed to wrapped function.
        kwargs: Keyword arguments to be passed to wrapped function.

    Returns: Either the result of the wrapped function evaluated with the
    supplied args and _kwargs, or a new LazyFunc instance.
    """
    if callable(args[0]):
        operator_precedence = 17
        other_func, *args = args

        def new_func(*x):
            return self.func(other_func(*x), *args, **kwargs)

        new_desc = (
            LazyFuncMeta._get_desc(self, operator_precedence)
            + "("
            + callable_name(other_func)
            + ")"
        )
        mf = LazyFunc(func=new_func, description=new_desc)
        mf._precedence = operator_precedence
        return mf
    else:  # when the function is called the kwargs supplied to the call take
        # precedence over those set elsewhere
        final_kwargs = self._kwargs | kwargs
        return self.func(*args, **final_kwargs)

__eq__(*instances) special

Return new instance LazyFunc(self == other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__floordiv__(*instances) special

Return new instance LazyFunc(self // other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__ge__(*instances) special

Return new instance LazyFunc(self >= other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__gt__(*instances) special

Return new instance LazyFunc(self > other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__invert__(*instances) special

Return new instance LazyFunc(~self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__le__(*instances) special

Return new instance LazyFunc(self <= other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__lshift__(*instances) special

Return new instance LazyFunc(self << other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__lt__(*instances) special

Return new instance LazyFunc(self < other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__matmul__(*instances) special

Return new instance LazyFunc(self @ other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__mod__(*instances) special

Return new instance LazyFunc(self % other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__mul__(*instances) special

Return new instance LazyFunc(self * other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__ne__(*instances) special

Return new instance LazyFunc(self != other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__neg__(*instances) special

Return new instance LazyFunc(-self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__or__(*instances) special

Return new instance LazyFunc(self | other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__pos__(*instances) special

Return new instance LazyFunc(+self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__pow__(*instances) special

Return new instance LazyFunc(self ** other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__radd__(*instances) special

Return new instance LazyFunc(other + self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__rand__(*instances) special

Return new instance LazyFunc(other & self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__rfloordiv__(*instances) special

Return new instance LazyFunc(other // self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__rlshift__(*instances) special

Return new instance LazyFunc(other << self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__rmatmul__(*instances) special

Return new instance LazyFunc(other @ self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__rmod__(*instances) special

Return new instance LazyFunc(other % self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__rmul__(*instances) special

Return new instance LazyFunc(other * self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__ror__(*instances) special

Return new instance LazyFunc(other | self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__rpow__(*instances) special

Return new instance LazyFunc(other ** self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__rrshift__(*instances) special

Return new instance LazyFunc(other >> self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__rshift__(*instances) special

Return new instance LazyFunc(self >> other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__rsub__(*instances) special

Return new instance LazyFunc(other - self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__rtruediv__(*instances) special

Return new instance LazyFunc(other / self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__rxor__(*instances) special

Return new instance LazyFunc(other ^ self), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__sub__(*instances) special

Return new instance LazyFunc(self - other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__truediv__(*instances) special

Return new instance LazyFunc(self / other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

__xor__(*instances) special

Return new instance LazyFunc(self ^ other), where other may be a scalar value or any other callable including another LazyFunc instance.

Source code in lazyfunc/lazy_func.py
def inner(*instances):
    new_func = LazyFuncMeta.new_function(operator, *instances)
    new_func.__signature__ = LazyFuncMeta.build_new_signature(instances)
    new_desc = LazyFuncMeta.description_from_operator(
        operator, *instances, reverse=reverse
    )
    mf = LazyFunc(func=new_func, description=new_desc)
    mf._precedence = operator.precedence
    return mf

is_equal(self, other)

Checks for equality between self and other.

To stay consistent with LazyFunc's other dunder methods, the __eq__ method lazily compares equality between the wrapped LazyFunc and other. Therefore, this method exists to check whether two unevaluated LazyFunc objects are equal, without calling them and comparing the results.

Examples:

>>> def my_function(x):
...     return x
>>> lf_auto_1 = LazyFunc(my_function)
>>> lf_auto_2 = LazyFunc(my_function)
>>> lf_named = LazyFunc(my_function, description='my_named_function')
>>> lf_auto_1.is_equal(lf_auto_2)
True
>>> lf_auto_1.is_equal(lf_named)
False
Source code in lazyfunc/lazy_func.py
def is_equal(self, other: callable) -> bool:
    """Checks for equality between self and other.

    To stay consistent with LazyFunc's other dunder methods, the `__eq__` method
    lazily compares equality between the wrapped LazyFunc and other. Therefore,
    this method exists to check whether two unevaluated LazyFunc objects are
    equal, without calling them and comparing the results.

    Examples:
        >>> def my_function(x):
        ...     return x
        >>> lf_auto_1 = LazyFunc(my_function)
        >>> lf_auto_2 = LazyFunc(my_function)
        >>> lf_named = LazyFunc(my_function, description='my_named_function')
        >>> lf_auto_1.is_equal(lf_auto_2)
        True
        >>> lf_auto_1.is_equal(lf_named)
        False
    """
    try:
        equal = self.description == other.description
    except AttributeError:
        msg = "Can only compare a LazyFunc instance with another LazyFunc"
        raise TypeError(msg)

    if not equal:
        msg = (
            "LazyFunc descriptions found to be not equal though may still be "
            "equivalent. "
        )
        warn(msg)

    return equal

No inplace operators.

Note that there are no inplace operators available. This is because to do so requires a new function to be created that depends on self, which is then assigned to self. This is a problem because the wrapped functions are passed by reference rather than by value, thus creating an infinite loop. One solution would be to create a copy of the old self, however this uses the same amount of memory as the non-inplace operation defeating the point. An alternative would be to simply call the non-inplace operation with the inplace syntax, however this would then be misleading. As a result inplace operations are not implemented for LazyFunc objects.