因此,我有一个用于串行API的大量消息Payload类,每个类都有许多不可变字段,一个解析方法和一些共享的方法.我构造它的方式是每个都将从字段行为的namedtuple继承,并从父类接收公共方法.但是,我在构造函数方面遇到了一些困难:
class Payload:
def test(self):
print("bar")
class DifferentialSpeed(Payload, namedtuple('DifferentialSpeed_',
'left_speed right_speed left_accel right_accel')):
__slots__ = ()
def __init__(self, **kwargs):
super(DifferentialSpeed, self).__init__(**kwargs)
# TODO: Field verification
print("foo")
@classmethod
def parse(self, raw):
# Dummy for now
return self(left_speed = 0.0, right_speed = 0.1,
left_accel = 0.2, right_accel = 0.3)
def __str__(self):
return "Left Speed: %fm/s\nRight Speed: %fm/s\n"\
"Left Acceleration: %fm/s^2\nRight Acceleration: %fm/s^2" % (
self.left_speed, self.right_speed, self.left_accel, self.right_accel)
payload = DifferentialSpeed.parse('dummy')
print(payload)
Run Code Online (Sandbox Code Playgroud)
这有效,但我得到以下警告:
DeprecationWarning: object.__init__() takes no parameters
super(DifferentialSpeed, self).__init__(**kwargs)
Run Code Online (Sandbox Code Playgroud)
如果我**kwargs …
inheritance multiple-inheritance super namedtuple python-3.x
我有一个init方法,通过广泛的层次结构使用和覆盖.然而,每个init调用都扩展了之前的工作.很自然地,我愿意:
@Override public void init() {
super.init();
}
Run Code Online (Sandbox Code Playgroud)
当然,这将确保一切都被调用和实例化.我想知道的是:我可以创建一种方法来确保调用超级方法吗?如果所有的init都没有调用,那么obejct就会出现故障,所以如果有人忘记调用,我想抛出异常或错误super.
TYFT~Aedon
短版(tl; dr)
我正在学习PySide,大多数在线教程都super用来初始化UI元素.这是重要的(即,更具可扩展性),还是品味问题?
澄清:当我在详细版本中更清楚时,这不是另一个通知线程,询问何时使用super(这已经在之前完成).相反,考虑到使用PySide教程的数量super,而不是<class>.__init__,我想如果用弄清楚super是PySide应用程序的标准?如果是这样,是因为super在使用PySide/PyQt时需要特别提到的(涉及解决继承问题)?或者这是品味问题.
详细版本
我是Python的新手,目前正在使用Zets教程学习PySide(http://zetcode.com/gui/pysidetutorial/firstprograms/).本教程的第二个示例包括:
from PySide import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.setGeometry(300,300,250,150)
self.setWindowTitle("PySide 101: Window the First!")
self.show()
app=QtGui.QApplication(sys.argv)
ex=Example()
sys.exit(app.exec_())
Run Code Online (Sandbox Code Playgroud)
这工作正常,但我从未使用过super.因此,我重写了上面的代码,成功地替换super了父类的更标准的显式调用:
QtGui.QWidget.__init__(self)
Run Code Online (Sandbox Code Playgroud)
但是,当我在网上搜索PySide教程时(例如,http://qt-project.org/wiki/PySide-Newbie-Tutorials ),它们都包括调用super.我的问题是:我应该super用于PySide脚本吗?
看来,super当你有继承的钻石,它倾向于解决多重继承的情况下,以合理的方式似乎是最有帮助的.是否super与PySide一起使用,因为这些钻石的案例占优势,我会面对更现实的复杂例子?[编辑:否:请参阅下面的答案.]
我为什么要问?为什么不直接使用super并完成它?
我在问,因为我用来学习Python的书(学习Python,由Lutz撰写)花了20多页关于这个主题super,并明确告诫不要使用它.他建议新的Python用户在使用它之前采用更传统,更明确的路线(例如,参见第832页,学习Python的第1041-1064页,第5版).他基本上将它描绘成一种非剧性的,神秘的,很少需要的新风格,刚开始时你应该非常谨慎地对待它,并认为它被有经验的用户过度使用.
此外,查看两个主要的PySide/PyQt项目(Spyder和pyqtgraph)的源代码,两者都没有使用super.One(Spyder)明确告诉贡献者出于兼容性原因而避免使用它(http://code.google.com/p/spyderlib/wiki/NoteForContributors). …
考虑以下一组表达式:
class T {{
/*1*/ super.toString(); // direct
/*2*/ T.super.toString(); // synthetic
Supplier<?> s;
/*3*/ s = super::toString; // synthetic
/*4*/ s = T.super::toString; // synthetic
}}
Run Code Online (Sandbox Code Playgroud)
这给出了以下结果:
class T {
T();
0 aload_0 [this]
1 invokespecial java.lang.Object() [8]
4 aload_0 [this]
5 invokespecial java.lang.Object.toString() : java.lang.String [10]
8 pop // ^-- direct
9 aload_0 [this]
10 invokestatic T.access$0(T) : java.lang.String [14]
13 pop // ^-- synthetic
14 aload_0 [this]
15 invokedynamic 0 get(T) : java.util.function.Supplier [21]
20 astore_1 [s] …Run Code Online (Sandbox Code Playgroud) 我的一位同事今天写了类似下面的代码,请我看看,我花了一段时间才发现错误:
class A():
def __init__(self):
print('A')
class B(A):
def __init__(self):
super(B).__init__()
b = B()
Run Code Online (Sandbox Code Playgroud)
这里的问题是在构造函数中没有self参数.让我感到惊讶的是,在这种情况下绝对没有任何事情发生,即没有错误,没有.包含的对象创建了什么?作为一个对象,它显然有一个构造函数,所以这是被调用的,但该对象是如何与?相关的?特别是,为什么这个有效的代码并没有在某处抛出异常?是一个具有一些实际用途的对象,那会是什么?super()Bsupersuper(B)Bsuper(B)
或者我应该只显式引用我想调用其方法的超类?
在引用它们的构造函数时重复超类的名称似乎很脆弱,但是这个页面http://fuhm.net/super-harmful/对使用super()做了一些很好的论据.
我有3个Django模板:
base.html文件
<title>{% block title %} SITE NAME {% endblock %}</title>
Run Code Online (Sandbox Code Playgroud)
default.html中
{% extends "base.html" %}
{% block title %} {{ block.super }} - SECTION NAME {% endblock %}
Run Code Online (Sandbox Code Playgroud)
main.html中
{% extends "default.html" %}
{% block title %} {{ block.super }} {% endblock %}
Run Code Online (Sandbox Code Playgroud)
我想在模板main.html中获取SITE NAME,即父块的父级内容.就像是
{{ block.super.super }}
Run Code Online (Sandbox Code Playgroud)
这可能吗?
我正在使用与此代码类似的somethign:
class BaseClass(object):
def __getattr__(self, attr):
return lambda:'1'
class SubClass(BaseClass):
def foo(self):
suffix = '2'
return super(SubClass, self).foo() + suffix
class SubClass2(SubClass):
def foo(self):
suffix = '3'
return super(SubClass2, self).foo() + suffix
o = SubClass2()
print o.foo()
Run Code Online (Sandbox Code Playgroud)
我希望看到'123'的输出,但我得到一个错误AttributeError: 'super' object has no attribute 'foo'.Python甚至没有尝试使用基类__getattr__.
如果不修改基类,并保持两个超级调用相似,我就无法获得我想要的输出.有没有合适的超级电话模式在这里适合我?
我知道super()会以某种方式覆盖getattr以执行它需要做的事情,但是我想问是否有任何合理的解决方法允许__getattr__在适当的时候调用子类.
考虑以下课程:
public abstract class AbstractClass {
public abstract String m();
public AbstractClass get(){
return new AbstractClass() {
@Override
public String m() {
return "Anonymous " + super.m(); //1, Compile-time erro
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
目前尚不清楚为何super禁止这种使用.在//1,发生以下错误
Cannot directly invoke the abstract method m() for the type AbstractClass
Run Code Online (Sandbox Code Playgroud)
所以,我咨询了JLS 15.11.2并没有找到阻止这些代码编译的限制.他们来了:
如果使用关键字super的表单出现在Object类的声明中,那么这是一个编译时错误,因为Object没有超类.
AbstractClass,但只有一个具体的子类,以下似乎也是有效的:使用关键字super的表单仅在实例方法,实例初始值设定项或构造函数中有效,或在类的实例变量的初始值设定项中有效.如果它们出现在其他任何地方,则会发生编译时错误.
如果当前类不是类T或T本身的内部类,则它是编译时错误.
当然,我可以使用AbstractClass.this.m(),但这不是我要问的.
根据ES6速记初始化,以下两种方法是相同的:
var person = {
name: "Person",
greet: function() {
return "Hello " + this.name;
}
};
Run Code Online (Sandbox Code Playgroud)
var person = {
name: "Person",
greet() {
return "Hello " + this.name;
}
};
Run Code Online (Sandbox Code Playgroud)
ES6的方式与之前的方式有什么不同吗?如果不是那么在它们里面使用"超级"也应该被视为相等,这不符合,请看下面的两个变量:
let person = {
greet(){
super.greet();
}
};
Object.setPrototypeOf(person, {
greet: function(){ console.log("Prototype method"); }
});
person.greet();
Run Code Online (Sandbox Code Playgroud)
let person = {
greet: function(){
super.greet(); // Throw error: Uncaught SyntaxError: 'super' keyword unexpected here
}
};
Object.setPrototypeOf(person, {
greet: function(){ console.log("Prototype method"); }
}); …Run Code Online (Sandbox Code Playgroud) super ×10
python ×4
java ×3
python-3.x ×2
block ×1
class ×1
django ×1
ecmascript-6 ×1
getattr ×1
getattribute ×1
inheritance ×1
java-8 ×1
namedtuple ×1
oop ×1
polymorphism ×1
pyqt ×1
pyside ×1
synthetic ×1