- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我遇到了一个我不明白的问题,而且它很复杂,所以我尽力在这里分解它。请看下面的实现。我的问题是:为什么父类调用它的子类的 __getitem__ 方法,而不是调用它自己的 __getitem__?
class Father(object):
''' Father class '''
def __init__(self,name,gender):
print('call __init__ Father')
self._name = name
# trying to call Father's __getitem__ here
self._gender=self[gender]
def __getitem__(self,key):
print('call __getitem__ Father')
return key
class Child(Father):
''' inherited from Father class '''
def __init__(self, name, gender, age=None):
print('call __init__ Child')
super(self.__class__, self).__init__(name, gender)
self._age = age
def __getitem__(self, key):
print('call __getitem__ Child')
if self._name == 'Marie' and self._age == None:
print('I am not sure, how old I am')
return super(self.__class__, self).__getitem__(key)
one=Child('Klaus','male','12')
other=Child('Marie','female')
将出现的错误信息是:
call __init__ Child
call __init__ Father
call __getitem__ Child
call __getitem__ Father
call __init__ Child
call __init__ Father
call __getitem__ Child
Traceback (most recent call last):
File "<ipython-input-58-2d97b09f6e25>", line 1, in <module>
runfile('F:/python-workspace/more-fancy-getitem-fix/test.py', wdir='F:/python-workspace/more-fancy-getitem-fix')
File "C:\Python27\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 601, in runfile
execfile(filename, namespace)
File "C:\Python27\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 66, in execfile
exec(compile(scripttext, filename, 'exec'), glob, loc)
File "F:/python-workspace/more-fancy-getitem-fix/test.py", line 26, in <module>
other=Child('Marie','female')
File "F:/python-workspace/more-fancy-getitem-fix/test.py", line 16, in __init__
super(self.__class__, self).__init__(name, gender)
File "F:/python-workspace/more-fancy-getitem-fix/test.py", line 6, in __init__
self._gender=self[gender]
File "F:/python-workspace/more-fancy-getitem-fix/test.py", line 21, in __getitem__
if self._name == 'Marie' and self._age == None:
AttributeError: 'Child' object has no attribute '_age'
我不希望有这种行为。我试图从 Father 继承 Child 添加功能,因此上述所有语法都是必要的,并且在我更复杂的代码中有意义。one=Child('Klaus','male','12') 的第一个示例运行顺利,我们已经可以看到,在父亲的构造函数中调用了 child 的 __getitem__ 。在 other=Child('Marie','female') 的第二个示例中,可以看出为什么这种反向调用让我感到困扰。这里的代码在定义 self._age = age 之前不会运行。
除了建议这个反之亦然的调用可能如何有用以及它的目的,我将非常感谢如何在父亲中显式调用自己的 __getitem__ 方法的解决方案。刚写完
self._gender=self.__getitem__(gender) #instead of
self._gender=self[gender]
不幸的是,它没有成功并产生同样的错误。
最佳答案
要修复,只需交换 Child
__init__
中的初始化顺序,以便 Child.__getitem__< 所需的
在需要之前被初始化:Child
属性
def __init__(self, name, gender, age=None):
print('call __init__ Child')
self._age = age
super(Child, self).__init__(name, gender)
这个修复是这个特定场景所独有的,但它通常也是正确的修复;通常,父类的唯一责任是尽量不要不必要地破坏子类化,但不能指望他们为子类计划创建新的类不变量并尝试提前容纳它们。子类应该完全了解父类,子类有责任确保它不会破坏父类的任何行为,在这种情况下,通过确保在父类之前定义所有新的必需属性可能会使用需要它们的方法。
至于为什么它会调用子类的 __getitem__
,这就是默认情况下子类化的工作方式(不仅在 Python 中,而且在大多数 OO 语言中)。 Father.__init__
从 Child.__init__
接收到的 self
仍然是一个 Child
对象,因此查找检查 __getitem__
首先在 Child
上。如果没有,您会产生令人困惑的行为,其中 Child
上的一些索引调用了 __getitem__
而有些则没有,这会使它变得非常不直观。
如果出于某种原因你绝对必须在 Father.__init__
中只使用 Father
的 __getitem__
,你只需要明确说明你调用的方法。代替 self[gender]
或 self.__getitem__(gender)
(两者都通过正常的查找过程),执行 Father.__getitem__(self, gender)
显式调用方法的 Father
版本(并且还要求您显式传递 self
,因为您使用的是未绑定(bind)方法而不是绑定(bind)方法).
另一种方法是定义一个指示实例未完全初始化的属性,并在父初始化器期间绕过子重载,以便在初始化期间调用父方法:
def __init__(self, name, gender, age=None):
print('call __init__ Child')
# Use double underscore prefix to make a private attribute of Child
# not directly visible to parent or lower level children so no risk
# of being reused by accident
self.__in_parent_init = True
super(Child, self).__init__(name, gender)
self.__in_parent_init = False
self._age = age
def __getitem__(self, key):
if self.__in_parent_init:
# Don't use Child specific features until Father initialized
return super(Child, self).__getitem__(key)
print('call __getitem__ Child')
if self._name == 'Marie' and self._age == None:
print('I am not sure, how old I am')
return super(Child, self).__getitem__(key)
关于python:继承类中的连续 __getitem__() 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36439150/
为了让我的代码几乎完全用 Jquery 编写,我想用 Jquery 重写 AJAX 调用。 这是从网页到 Tomcat servlet 的调用。 我目前情况的类似代码: var http = new
我想使用 JNI 从 Java 调用 C 函数。在 C 函数中,我想创建一个 JVM 并调用一些 Java 对象。当我尝试创建 JVM 时,JNI_CreateJavaVM 返回 -1。 所以,我想知
环顾四周,我发现从 HTML 调用 Javascript 函数的最佳方法是将函数本身放在 HTML 中,而不是外部 Javascript 文件。所以我一直在网上四处寻找,找到了一些简短的教程,我可以根
我有这个组件: import {Component} from 'angular2/core'; import {UserServices} from '../services/UserService
我正在尝试用 C 实现一个简单的 OpenSSL 客户端/服务器模型,并且对 BIO_* 调用的使用感到好奇,与原始 SSL_* 调用相比,它允许一些不错的功能。 我对此比较陌生,所以我可能会完全错误
我正在处理有关异步调用的难题: 一个 JQuery 函数在用户点击时执行,然后调用一个 php 文件来检查用户输入是否与数据库中已有的信息重叠。如果是这样,则应提示用户确认是否要继续或取消,如果他单击
我有以下类(class)。 public Task { public static Task getInstance(String taskName) { return new
嘿,我正在构建一个小游戏,我正在通过制作一个数字 vector 来创建关卡,该数字 vector 通过枚举与 1-4 种颜色相关联。问题是循环(在 Simon::loadChallenge 中)我将颜
我有一个java spring boot api(数据接收器),客户端调用它来保存一些数据。一旦我完成了数据的持久化,我想进行另一个 api 调用(应该处理持久化的数据 - 数据聚合器),它应该自行异
首先,这涉及桌面应用程序而不是 ASP .Net 应用程序。 我已经为我的项目添加了一个 Web 引用,并构建了各种数据对象,例如 PayerInfo、Address 和 CreditCard。但问题
我如何告诉 FAKE 编译 .fs文件使用 fsc ? 解释如何传递参数的奖励积分,如 -a和 -target:dll . 编辑:我应该澄清一下,我正在尝试在没有 MSBuild/xbuild/.sl
我使用下划线模板配置了一个简单的主干模型和 View 。两个单独的 API 使用完全相同的配置。 API 1 按预期工作。 要重现该问题,请注释掉 API 1 的 URL,并取消注释 API 2 的
我不确定什么是更好的做法或更现实的做法。我希望从头开始创建目录系统,但不确定最佳方法是什么。 我想我在需要显示信息时使用对象,例如 info.php?id=100。有这样的代码用于显示 Game.cl
from datetime import timedelta class A: def __abs__(self): return -self class B1(A):
我在操作此生命游戏示例代码中的数组时遇到问题。 情况: “生命游戏”是约翰·康威发明的一种细胞自动化技术。它由一个细胞网格组成,这些细胞可以根据数学规则生存/死亡/繁殖。该网格中的活细胞和死细胞通过
如果我像这样调用 read() 来读取文件: unsigned char buf[512]; memset(buf, 0, sizeof(unsigned char) * 512); int fd;
我用 C 编写了一个简单的服务器,并希望调用它的功能与调用其他 C 守护程序的功能相同(例如使用 ./ftpd start 调用它并使用 ./ftpd stop 关闭该实例)。显然我遇到的问题是我不知
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
我希望能够从 cmd 在我的 Windows 10 计算机上调用 python3。 我已重新安装 Python3.7 以确保选择“添加到路径”选项,但仍无法调用 python3 并使 CMD 启动 P
我是一名优秀的程序员,十分优秀!