from typing import Iterable
from typing import Callable
from typing import Any


def delegate_factory(cls: type, delegate_attrs: Iterable[str]) -> Callable[[Any], Any]:
    """
    Create factory function that searches object `o` for `delegate_attrs`
    and check is any of these attributes have `cls` type. If no such
    attributes found it calls `cls(o)` to cast it into desired type.

    >>> class Z:
    ...     def __int__(self):
    ...         return 7
    ...
    >>> x = Z()
    >>> x.a = 5
    >>> y = Z()
    >>> y.b = 3
    >>> q = Z()
    >>> q.b = 'str'
    >>> z = Z()
    >>> factory = delegate_factory(int, ["a","b"])
    >>> factory(x)
    5
    >>> factory(y)
    3
    >>> factory(q)
    7
    >>> factory(z)
    7
    """

    def cls_factory(o: Any) -> Any:
        for posible_delegate in delegate_attrs:
            if hasattr(o, posible_delegate):
                candidate_obj = getattr(o, posible_delegate)
                if isinstance(candidate_obj, cls):
                    return candidate_obj
        return cls(o)

    return cls_factory