Похоже, вы ищете что-то вроде типов протоколов, предложенных в PEP 544 а>. Этот PEP еще не утвержден (и, возможно, еще не имеет полной реализации), поэтому может пройти некоторое время, прежде чем вы получите нужную вам функцию (как минимум Python 3.8).
В любом случае, согласно PEP, протоколы позволят вам описать своего рода абстрактный тип на основе того, какие у него есть методы и атрибуты, при этом конкретные типы не должны знать о протоколе или делать что-то конкретное (ему не нужно наследовать от абстрактный базовый класс, просто имейте необходимые методы). Это похоже на то, как вы можете настроить работу isinstance
и issubclass
с помощью метаклассов, но это работает со статической проверкой типов, а не только во время выполнения.
Например, итераторы в Python — это существующий протокол, который реализуют многие несвязанные классы. Если PEP будет одобрен и реализован, вам больше не нужно будет объявлять пользовательский тип итератора как наследуемый от typing.Iterator
, он определит это автоматически, просто потому, что класс имеет методы __iter__
и __next__
.
В вашем примере вы можете создать протокол A_Like
, для которого требуется метод to_A
:
class A_Like(typing.Protocol):
def to_A(self) -> A:
...
Затем вы реализуете A.to_A
с помощью простого return self
, а B.to_A
выполняет соответствующее преобразование. Оба класса будут рассматриваться как соответствующие типу протокола A_Like
, поэтому def foo(a: A_Like)
удовлетворит средства проверки типов (тело класса должно выполнить a = a.to_A()
перед вызовом каких-либо A
конкретных методов).
Вы можете сделать это сейчас с наследованием от общего абстрактного базового класса (который может быть простым миксином), но это определенно не так элегантно, как с протоколами. Другой вариант, если у вас не так много классов, которые нужно преобразовать, — просто использовать объявления типов Union
: def foo(a: Union[A, B])
person
Blckknght
schedule
19.06.2018
A
иB
? Как работает конвертация? Вы могли бы сделать это, написав декоратор, который отправляет все входные данные правильному конвертеру, возможно, через какой-то общая функция одиночной отправки - person Patrick Haugh   schedule 19.06.2018A
, может написать неявный преобразователь для любого типаT
, который будет автоматически вызываться по мере необходимости, пока преобразователь находится в области видимости (по крайней мере, так это работает в Scala). ) - person bbarker   schedule 19.06.2018b_to_a
. В зависимости от того, какую операцию вы хотите выполнить с объектом, вы можете использовать утиную типизацию, чтобы оснастить определенные классы для выполнения этой операции, а затем использовать Абстрактный базовый класс для описания этой группы классов. - person Patrick Haugh   schedule 19.06.2018