我可以在 Python 中为继承的方法创建别名吗?

     2023-02-23     159

关键词:

【中文标题】我可以在 Python 中为继承的方法创建别名吗?【英文标题】:Can I create an alias to an inherited method in Python? 【发布时间】:2017-03-30 02:21:03 【问题描述】:

我的 Python 程序中有一个非常复杂的类层次结构。该程序有许多工具,要么是模拟器,要么是编译器。两种共享一些方法,所以有一个Shared 类作为所有类的基类。一个精简的示例如下所示:

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 来引用这个方法。

我可以写一个装饰器来返回_Prepare而不是_PrepareSimulator吗?但是如何在装饰器中找到_Prepare

我也需要调整方法绑定吗?

【问题讨论】:

您可以将_PrepareSimulation 定义为Shared._Prepare 的别名,因此:_PrepareSimulation = Shared._Prepare。但我完全不确定你为什么要这样做。你到底想达到什么目的? 你有 _PrepareSimulation_PrepareSimulator - 是不同的还是错字? typo :) 更高级别的类可以覆盖方法,从而在需要时插入它们的逻辑。大多数类使用基类的功能 你不需要一个基类来获取一些常用的方法,Python 有 Duck Typing。 【参考方案1】:

我设法创建了一个基于装饰器的解决方案,以确保类型安全。第一个装饰器将别名注释为本地方法。需要保护别名目标。需要第二个装饰器来替换 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 引用了一个方法“_Prepare”,它不是类层次结构的一部分:模拟器 -> 共享 -> 对象。

【讨论】:

如何在css或sass中为类名起别名

...eincssorsass【发布时间】:2012-10-3109:28:02【问题描述】:我可以为css类创建别名吗?我正在使用这种很棒的字体,并且我正在尝试为某些图标类创建别名。这样.icon-globe也将调用.globe。我怎样才能完成这样的事情?【问题讨论】:... 查看详情

在 pipenv 项目中为 python 文件创建命令行别名

】在pipenv项目中为python文件创建命令行别名【英文标题】:makingacommandlinealiastoapythonfileinapipenvproject【发布时间】:2018-07-0504:55:58【问题描述】:我一直在使用pipenv制作一个python项目,我希望能够从我的(linux)系统上的任何位置在... 查看详情

这是使用 API 在 Python 中为 Braintree 创建订阅的正确方法吗

】这是使用API在Python中为Braintree创建订阅的正确方法吗【英文标题】:IsthistherightwaytocreateasubscriptionforBraintreeinPythonusingtheAPI【发布时间】:2018-04-1619:03:46【问题描述】:为了澄清问题,我在这里提出这个问题并分享我迄今为止所... 查看详情

在python中为打印设置命令别名?

...发布时间】:2012-08-2420:28:50【问题描述】:在bash中,你可以给命令一个别名,如下所示:aliase=echosetaliase="echoblah"我想知道如何在Python中做同样的事情。我知道你可以给类别名,但是当我尝试给命令(例如print语句)一个别名时... 查看详情

我可以在 redshift 中为外部表添加别名以删除架构名称吗?

】我可以在redshift中为外部表添加别名以删除架构名称吗?【英文标题】:CanIaliasanexternaltableinredshifttoremovetheschemaname?【发布时间】:2018-09-2717:38:01【问题描述】:我们想将表迁移到Spectrum,这需要定义一个外部架构createexternalsche... 查看详情

可以在 Python Flask 中为不同的用户创建不同的会话超时长度吗?

】可以在PythonFlask中为不同的用户创建不同的会话超时长度吗?【英文标题】:PossibletocreatedifferentsessiontimeoutlengthsfordifferentusersinPythonFlask?【发布时间】:2017-08-3115:39:47【问题描述】:我有一个Angular/FlaskWeb应用程序,我正在尝试... 查看详情

如何在 MySQL 中为数据库起别名?

...够在不关闭系统的情况下重命名实时生产数据库。我想我可以将数据库别名为新名称,在闲暇时更改和部署连接到它的代码,并最终删除旧别名。如果有更好的方法可以做到这一点,请告诉我。【问题讨论】:如果MySQL没有内置... 查看详情

在 Spring Data 中为同一 QueryDSL 路径创建多个别名

...尝试扩展默认存储库实现中内置的基本相等测试,以便我可以使用 查看详情

vscode自动导入类型python中的继承可以自动完成吗?

】vscode自动导入类型python中的继承可以自动完成吗?【英文标题】:Canautocompletionforinheritanceinvscodeauto-importtypespython?【发布时间】:2021-07-1015:14:39【问题描述】:在覆盖子方法的情况下,在vscode中为python使用自动补全时,自动补... 查看详情

使用继承在 C++ 中为 DCI 模拟角色

...http://tidyjava.com/dci-architecture-visionary/)在我看来,“角色”可以通过创建从基类继承并可以访问所有私有成员的派生类来模拟。这是一个合理的说法吗?或者 查看详情

我可以在 Javascript 中为我创建的对象创建自定义事件吗?

】我可以在Javascript中为我创建的对象创建自定义事件吗?【英文标题】:CanIcreateacustomeventinJavascriptforanobjectIcreated?【发布时间】:2011-05-1606:50:59【问题描述】:假设我有一个带有返回自身的成员函数的对象:/*--Object1--*/functionObj... 查看详情

如何在 Vim 中为命令创建别名?

】如何在Vim中为命令创建别名?【英文标题】:HowtocreateanaliasforacommandinVim?【发布时间】:2011-04-2204:15:37【问题描述】:Vim是我编程时首选的文本编辑器,因此我总是遇到一个特别烦人的问题。通常,当我需要快速保存缓冲区并... 查看详情

你可以在 package.json 中为 npm 脚本设置别名吗?

】你可以在package.json中为npm脚本设置别名吗?【英文标题】:Canyousetaliasesfornpmscriptsinsidepackage.json?【发布时间】:2019-03-0916:57:39【问题描述】:我有一个项目写在Typescript本地开发时:ts-node作为开发依赖安装,命令是tostart:"ts-node... 查看详情

我可以在 Golang 中创建一个类型的别名吗?

】我可以在Golang中创建一个类型的别名吗?【英文标题】:CanIcreateanaliasofatypeinGolang?【发布时间】:2017-02-2611:00:28【问题描述】:我正在努力学习围棋。我在go:gopkg.in/fatih/set.v0中找到了一个Set的简洁实现,但我更喜欢用一个比set... 查看详情

C++ 虚拟方法:我必须在父类中为子级和父级不共享的每个方法创建一个虚拟方法吗?

】C++虚拟方法:我必须在父类中为子级和父级不共享的每个方法创建一个虚拟方法吗?【英文标题】:C++VirtualMethods:MustIcreateavirtualmethodintheparentclassforeverymethodthatthechildandparentdonotshare?【发布时间】:2014-08-0422:06:05【问题描述】:... 查看详情

在 python 中为大文件创建校验和的最快方法

】在python中为大文件创建校验和的最快方法【英文标题】:thefastestwaytocreatechecksumforlargefilesinpython【发布时间】:2010-12-0416:48:00【问题描述】:我需要通过网络传输大文件,并且需要每小时为它们创建校验和。所以生成校验和的... 查看详情

我可以在 Windows 中为 Linux 平台创建应用程序吗?

】我可以在Windows中为Linux平台创建应用程序吗?【英文标题】:CanicreateapplicationinWindowsforLinuxplatform?【发布时间】:2014-02-1404:17:40【问题描述】:我在C#.Net编程方面有大约4年的经验,我正在开发一个客户端服务器应用程序。服务... 查看详情

我可以在 Visual Studio 中为 UnitTest/LoadTest 创建自定义 TestContext 计时器吗?

】我可以在VisualStudio中为UnitTest/LoadTest创建自定义TestContext计时器吗?【英文标题】:CanIcreateacustomTestContexttimerforUnitTest/LoadTestinVisualStudio?【发布时间】:2013-05-2921:10:18【问题描述】:我的一些单元测试有一个在循环中定义的睡眠... 查看详情