我可以为 Python 中的继承方法创建别名吗?
Can I create an alias to an inherited method in Python?
我的 Python 程序中有一个非常复杂的 class 层次结构。该程序有很多工具,要么是模拟器,要么是编译器。这两种方法共享一些方法,因此有一个 Shared
class 作为所有 class 的基础 class。精简示例如下所示:
class Shared:
__TOOL__ = None
def _Prepare(self):
print("Preparing {0}".format(self.__TOOL__))
class Compiler(Shared):
def _Prepare(self):
print("do stuff 1")
super()._Prepare()
print("do stuff 2")
def _PrepareCompiler(self):
print("do stuff 3")
self._Prepare()
print("do stuff 4")
class Simulator(Shared):
def _PrepareSimulator(self): # <=== how to create an alias here?
self._Prepare()
class Tool1(Simulator):
__TOOL__ = "Tool1"
def __init__(self):
self._PrepareSimulator()
def _PrepareSimulator(self):
print("do stuff a")
super()._PrepareSimulator()
print("do stuff b")
我可以将方法 Simulator._PrepareSimulator
定义为 Simulator/Shared._Prepare
的别名吗?
我知道我可以创建本地别名,例如:__str__ = __repr__
,但在我的情况下,_Prepare
在上下文中是未知的。我没有 self
也没有 cls
来引用这个方法。
我可以为 return _Prepare
而不是 _PrepareSimulator
编写装饰器吗?但是我如何在装饰器中找到 _Prepare
?
我是否也需要调整方法绑定?
我设法创建了一个基于装饰器的解决方案,它确保了类型安全。第一个装饰器注释了本地方法的别名。需要它来保护别名目标。需要第二个装饰器来替换 Alias
实例并检查别名是否指向类型层次结构中的方法。
装饰器/别名定义:
from inspect import getmro
class Alias:
def __init__(self, method):
self.method = method
def __call__(self, func):
return self
def HasAliases(cls):
def _inspect(memberName, target):
for base in getmro(cls):
if target.__name__ in base.__dict__:
if (target is base.__dict__[target.__name__]):
setattr(cls, memberName, target)
return
else:
raise NameError("Alias references a method '{0}', which is not part of the class hierarchy: {1}.".format(
target.__name__, " -> ".join([base.__name__ for base in getmro(cls)])
))
for memberName, alias in cls.__dict__.items():
if isinstance(alias, Alias):
_inspect(memberName, alias.method)
return cls
用法示例:
class Shared:
__TOOL__ = None
def _Prepare(self):
print("Preparing {0}".format(self.__TOOL__))
class Shared2:
__TOOL__ = None
def _Prepare(self):
print("Preparing {0}".format(self.__TOOL__))
class Compiler(Shared):
def _Prepare(self):
print("do stuff 1")
super()._Prepare()
print("do stuff 2")
def _PrepareCompiler(self):
print("do stuff 3")
self._Prepare()
print("do stuff 4")
@HasAliases
class Simulator(Shared):
@Alias(Shared._Prepare)
def _PrepareSimulatorForLinux(self): pass
@Alias(Shared._Prepare)
def _PrepareSimulatorForWindows(self): pass
class Tool1(Simulator):
__TOOL__ = "Tool1"
def __init__(self):
self._PrepareSimulator()
def _PrepareSimulator(self):
print("do stuff a")
super()._PrepareSimulatorForLinux()
print("do stuff b")
super()._PrepareSimulatorForWindows()
print("do stuff c")
t = Tool1()
将 @Alias(Shared._Prepare)
设置为 @Alias(Shared2._Prepare)
将引发异常:
NameError: Alias references a method '_Prepare', which is not part of the class hierarchy: Simulator -> Shared -> object.
我的 Python 程序中有一个非常复杂的 class 层次结构。该程序有很多工具,要么是模拟器,要么是编译器。这两种方法共享一些方法,因此有一个 Shared
class 作为所有 class 的基础 class。精简示例如下所示:
class Shared:
__TOOL__ = None
def _Prepare(self):
print("Preparing {0}".format(self.__TOOL__))
class Compiler(Shared):
def _Prepare(self):
print("do stuff 1")
super()._Prepare()
print("do stuff 2")
def _PrepareCompiler(self):
print("do stuff 3")
self._Prepare()
print("do stuff 4")
class Simulator(Shared):
def _PrepareSimulator(self): # <=== how to create an alias here?
self._Prepare()
class Tool1(Simulator):
__TOOL__ = "Tool1"
def __init__(self):
self._PrepareSimulator()
def _PrepareSimulator(self):
print("do stuff a")
super()._PrepareSimulator()
print("do stuff b")
我可以将方法 Simulator._PrepareSimulator
定义为 Simulator/Shared._Prepare
的别名吗?
我知道我可以创建本地别名,例如:__str__ = __repr__
,但在我的情况下,_Prepare
在上下文中是未知的。我没有 self
也没有 cls
来引用这个方法。
我可以为 return _Prepare
而不是 _PrepareSimulator
编写装饰器吗?但是我如何在装饰器中找到 _Prepare
?
我是否也需要调整方法绑定?
我设法创建了一个基于装饰器的解决方案,它确保了类型安全。第一个装饰器注释了本地方法的别名。需要它来保护别名目标。需要第二个装饰器来替换 Alias
实例并检查别名是否指向类型层次结构中的方法。
装饰器/别名定义:
from inspect import getmro
class Alias:
def __init__(self, method):
self.method = method
def __call__(self, func):
return self
def HasAliases(cls):
def _inspect(memberName, target):
for base in getmro(cls):
if target.__name__ in base.__dict__:
if (target is base.__dict__[target.__name__]):
setattr(cls, memberName, target)
return
else:
raise NameError("Alias references a method '{0}', which is not part of the class hierarchy: {1}.".format(
target.__name__, " -> ".join([base.__name__ for base in getmro(cls)])
))
for memberName, alias in cls.__dict__.items():
if isinstance(alias, Alias):
_inspect(memberName, alias.method)
return cls
用法示例:
class Shared:
__TOOL__ = None
def _Prepare(self):
print("Preparing {0}".format(self.__TOOL__))
class Shared2:
__TOOL__ = None
def _Prepare(self):
print("Preparing {0}".format(self.__TOOL__))
class Compiler(Shared):
def _Prepare(self):
print("do stuff 1")
super()._Prepare()
print("do stuff 2")
def _PrepareCompiler(self):
print("do stuff 3")
self._Prepare()
print("do stuff 4")
@HasAliases
class Simulator(Shared):
@Alias(Shared._Prepare)
def _PrepareSimulatorForLinux(self): pass
@Alias(Shared._Prepare)
def _PrepareSimulatorForWindows(self): pass
class Tool1(Simulator):
__TOOL__ = "Tool1"
def __init__(self):
self._PrepareSimulator()
def _PrepareSimulator(self):
print("do stuff a")
super()._PrepareSimulatorForLinux()
print("do stuff b")
super()._PrepareSimulatorForWindows()
print("do stuff c")
t = Tool1()
将 @Alias(Shared._Prepare)
设置为 @Alias(Shared2._Prepare)
将引发异常:
NameError: Alias references a method '_Prepare', which is not part of the class hierarchy: Simulator -> Shared -> object.