- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我观察到类继承有一个奇怪的效果。对于我正在从事的项目,我正在创建一个类来充当另一个模块类的包装器。
我正在使用第 3 方 aeidon 模块(用于处理字幕文件),但问题可能不太具体。
这是您通常使用该模块的方式...
project = aeidon.Project()
project.open_main(path)
这里是使用中的'wrapper'类的例子(当然真正的类有很多方法):
class Wrapper(aeidon.Project):
pass
project = Wrapper()
project.open_main(path)
上述代码在执行时引发了一个AttributeError。但是,以下工作与我最初预期的一样:
junk = aeidon.Project()
project = Wrapper()
project.open_main(path)
我把这个问题命名为 spooky action at a distance 因为我怀疑它涉及环境中的全局变量/对象,但我不知道。
我最终使用组合来解决这个问题(即 self.project = aeidon.Project()
),但我仍然对此感到好奇。谁能解释一下这是怎么回事?
这是回溯:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-5-fe548abd7ad0> in <module>()
----> 1 project.open_main(path)
/usr/lib/python3/dist-packages/aeidon/deco.py in wrapper(*args, **kwargs)
208 def wrapper(*args, **kwargs):
209 frozen = args[0].freeze_notify()
--> 210 try: return function(*args, **kwargs)
211 finally: args[0].thaw_notify(frozen)
212 return wrapper
/usr/lib/python3/dist-packages/aeidon/agents/open.py in open_main(self, path, encoding)
161 format = aeidon.util.detect_format(path, encoding)
162 self.main_file = aeidon.files.new(format, path, encoding)
--> 163 subtitles = self._read_file(self.main_file)
164 self.subtitles, sort_count = self._sort_subtitles(subtitles)
165 self.set_framerate(self.framerate, register=None)
/usr/lib/python3/dist-packages/aeidon/project.py in __getattr__(self, name)
116 return self._delegations[name]
117 except KeyError:
--> 118 raise AttributeError
119
120 def __init__(self, framerate=None, undo_limit=None):
AttributeError:
无论是否调用 Project 的 __init__()
,我都试过了。显然这不是正常情况下真正应该做的事情,我只是很困惑为什么 Wrapper() 只能在创建垃圾 aeidon.Project() 后才能按预期运行。
最佳答案
它将 aedion.agents
包中的类的方法添加到类中,以便文档生成器在提取文档字符串和其他信息时包含这些方法,使用 ProjectMeta
metaclass :
class ProjectMeta(type):
"""
Project metaclass with delegated methods added.
Public methods are added to the class dictionary during :meth:`__new__`
in order to fool Sphinx (and perhaps other API documentation generators)
into thinking that the resulting instantiated class actually contains those
methods, which it does not since the methods are removed during
:meth:`Project.__init__`.
"""
但是,如果使用这些方法,则不会正确绑定(bind)。
Project.__init__
方法调用 Project._init_delegations()
.此方法删除类中的委托(delegate)方法:
# Remove class-level function added by ProjectMeta.
if hasattr(self.__class__, attr_name):
delattr(self.__class__, attr_name)
注意这里使用了self.__class__
。这是必需的,因为如果在类中找到该方法,Python 将不会通过 __getattr__
Hook 查找委托(delegate)方法。
委托(delegate)方法绑定(bind)到专用代理实例,因此实际上是委托(delegate)给该代理:
agent = getattr(aeidon.agents, agent_class_name)(self)
# ...
attr_value = getattr(agent, attr_name)
# ...
self._delegations[attr_name] = attr_value
当您围绕此类创建包装器时,删除 步骤会失败。 self.__class__
是您的包装器,而不是基础 Project
类。因此方法绑定(bind)不正确;元类提供的方法被绑定(bind),并且永远不会调用 __getattr__
Hook 来查找委托(delegate)的方法:
>>> import aeidon
>>> class Wrapper(aeidon.Project): pass
...
>>> wrapper = Wrapper()
>>> wrapper.open_main
<bound method Wrapper.open_main of <__main__.Wrapper object at 0x1106313a8>>
>>> wrapper.open_main.__self__
<__main__.Wrapper object at 0x1106313a8>
>>> wrapper._delegations['open_main']
<bound method OpenAgent.open_main of <aeidon.agents.open.OpenAgent object at 0x11057e780>>
>>> wrapper._delegations['open_main'].__self__
<aeidon.agents.open.OpenAgent object at 0x11057e780>
因为 Project
上的 open_main
方法仍然存在:
>>> Project.open_main
<function OpenAgent.open_main at 0x110602bf8>
一旦创建了 Project
的实例,这些方法就会从类中删除:
>>> Project()
<aeidon.project.Project object at 0x1106317c8>
>>> Project.open_main
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'Project' has no attribute 'open_main'
并且您的包装器将开始工作,因为现在已找到委托(delegate)的 open_main
:
>>> wrapper.open_main
<bound method OpenAgent.open_main of <aeidon.agents.open.OpenAgent object at 0x11057e780>>
>>> wrapper.open_main.__self__
<aeidon.agents.open.OpenAgent object at 0x11057e780>
您的包装器必须自己进行删除:
class Wrapper(aeidon.Project):
def __init__(self):
super().__init__()
for name in self._delegations:
if hasattr(aeidon.Project, name):
delattr(aeidon.Project, name)
请注意,如果 aedion
维护者将 self.__class__
替换为 __class__
(没有 self
)他们的代码和您的子类方法仍然有效,而无需再次手动清理类。这是因为在 Python 3 中,__class__
引用 in methods 是一个自动闭包变量,指向定义方法的类。对于 Project._init_delegations()
,那将是 Project
。或许您可以就此提交错误报告。
关于Python 类继承 - 幽灵般的 Action ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27720339/
当包裹在 EmberJS Controller 的 actions 中时,如何从另一个 Action 调用一个 Action ? 使用现已弃用的方式定义操作的原始代码: //app.js App.In
我有一个 Action (一个yaml文件),用于将docker镜像部署到Google Cloud Run。 我希望收到通知构建和推送结果的Slack或电子邮件。 构建操作完成后,如何触发消息操作?
Selenium 的 actions 类中存在的 tick(Action action) 和 tick(Interaction...actions) 方法的用途是什么? 是否与点击任何 webElem
简短的背景故事 我们目前为数百名用户提供对话操作。我们在过去三年中为我们的一位客户开发了这个 Action 作为“工作”。正如我们最近发现的那样,我们会受到对话行为的影响。 当然,我们现在正在研究如何
考虑系统用户可以并发方式执行两个操作,第一个操作 (A1) 仅对用户的订单执行,第二个操作 (A2) 包括在执行时执行 (A1),如下面的使用所述-案例图..((考虑A1完全执行U1,A2完全执行U2
我正在为 android 中的 ActionBar 而苦苦挣扎。 这是我的问题:我的操作项没有显示在操作栏中,而是堆叠在操作溢出中,无论我做什么.. 我花了一天的时间寻找解决方案,但我似乎找不到缺少的
我正在构建一个工作流,其中一个操作为工作流中的一个步骤提供条件。我该如何使用这个值? 该操作的值为空,因此计算结果为 false,并且从未部署过任何内容... jobs: build: s
鉴于您有一些全局 View (例如,显示加载屏幕),您可能希望在许多情况下发生这种情况,为该行为创建一个 Action 创建者/ Action 对还是为相关 Action 创建 reducer 更合适
我有一个使用 DialogFlow 构建的 Actions on Google 代理,其中包含多个操作(例如 actions.intent.MAIN 和 get_day_of_week)。 当我在 3
是否可以从我的 action.yml 文件中引用另一个 GitHub 操作? 请注意,我在这里谈论的是操作,而不是工作流程。我知道这可以通过工作流来完成,但是操作可以引用其他操作吗? 最佳答案 答案似
在 Vuex 操作中,我们有以下实现。 async actionA({ commit, dispatch }) { const data = this.$axios.$get(`/apiUrl`)
我正在将我的应用程序服务器从 Jboss 4.2 迁移到 7.1。我在 Struts 配置中收到以下错误。 struts.xml 中定义的 Action 被调用,而 Action 包中的操作未被调用。
我向 ActLand 发送请求,然后 intercept(),如果没有登录则重定向到 Login.jsp。 struts.xml:
我有一个 Action 创建器,它接受一个 id 和一个回调函数。它向服务器发送请求以执行某些操作并返回一个虚拟操作。我在这里想做的就是调用回调函数并退出,因为该虚拟操作对我来说没有用处,例如喜欢帖子
我已经使用 Html.Action 方法调用了另一个 View 。当用户单击操作链接时,我想在 subview 内使用参数调用相同的操作。 当我写这段代码时,我得到了这个错误信息: Html.Acti
是 public event Action delt = () => { Console.WriteLine("Information"); }; 的重载版本 Action delg = (a, b)
countresultsfrom.addActionListener(new ActionListener() { public void actionPerforme
我刚刚看到一个 brand-new video在 Rx 框架上,一个特别的签名引起了我的注意: Scheduler.schedule(this IScheduler, Action) 在 23:55,
我创建了一个在我的开发者帐户中完美运行的 DialogFlow 应用程序。 但我需要以另一个用户的身份对其进行测试,因此在我的 Google Action 模拟器中,我添加了另一个测试帐户作为项目的所
我正在尝试实现消息存储拦截器以在我的 JSp 上显示 ActionMessage,但无法访问 ActionMessage。有人可以提供一个链接如何实现消息存储拦截器吗? 最佳答案 这是我的一个应用程序
我是一名优秀的程序员,十分优秀!