我在New-Style Classes中发现了子类化和字典更新的一个奇怪问题:
Python 2.6.2 (r262:71605, Apr 14 2009, 22:40:02) [MSC v.1500 32 bit (Intel)] on
win32
>>> class a(object):
... def __init__(self, props={}):
... self.props = props
...
>>> class b(a):
... def __init__(self, val = None):
... super(b, self).__init__()
... self.props.update({'arg': val})
...
>>> class c(b):
... def __init__(self, val):
... super(c, self).__init__(val)
...
>>> b_inst = b(2)
>>> b_inst.props
{'arg': 2}
>>> c_inst = c(3)
>>> c_inst.props
{'arg': 3}
>>> b_inst.props
{'arg': 3}
>>>
Run Code Online (Sandbox Code Playgroud)
在debug中,在第二个call(c(3))中,您可以看到a …
假设我有一个用于添加/编辑产品的表单(字段'user'是我的用户的外键),它是从两个单独的视图函数触发的 - 添加/编辑:
def product_add(request):
userprofile = UserProfile.objects.get(user=request.user)
if request.method == 'POST':
form = ProductAddForm(request.POST, request.FILES,)
if form.is_valid():
form.save(user=request.user)
else:
form = ProductAddForm()
return render_to_response('products/product_add.html', {
'form':form, 'user':request.user,
}, context_instance=RequestContext(request))
def product_edit(request, id):
product = get_object_or_404(Product, id=id, user=request.user)
if product.user.id!=request.user.id:
raise Http404
if request.method == 'POST':
form = ProductAddForm(request.POST, request.FILES, instance=product)
if form.is_valid():
form.save(user=request.user)
else:
form = ProductAddForm(instance=product)
return render_to_response('products/product_edit.html', {
'form':form, 'user':request.user,
}, context_instance=RequestContext(request))
Run Code Online (Sandbox Code Playgroud)
表单的save方法如下所示:
def save(self, user, *args, **kwargs):
self.instance.user = user
post = super(ProductAddForm, self).save(*args, **kwargs)
post.save() …Run Code Online (Sandbox Code Playgroud) 正如标题所说,你怎么记得super论证的顺序?我错过了什么地方的助记符?
经过多年的Python编程,我仍然要查找它:(
(记录,它是super(Type, self))
为什么我不能super用来获取类的超类的方法?
例:
Python 3.1.3
>>> class A(object):
... def my_method(self): pass
>>> class B(A):
... def my_method(self): pass
>>> super(B).my_method
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
super(B).my_method
AttributeError: 'super' object has no attribute 'my_method'
Run Code Online (Sandbox Code Playgroud)
(当然,这是一个简单的案例,我可以做A.my_method,但我需要这个钻石继承案例.)
根据super文件,似乎我想要的应该是可能的.这是super文件:(强调我的)
super()- >相同super(__class__, <first argument>)
super(type)- >未绑定的超级对象
super(type, obj)- >绑定super对象; 要求isinstance(obj, type)super(type,type2) - >绑定超级对象; 需要issubclass(type2,type)
[编辑的非相关示例]
我有一个必须用参数构造的基类.在子类中,我需要在构造基类之前准备这个参数,但是在Java中必须先调用super.处理这种情况的最佳方法是什么(见下面的简单示例).
class BaseClass {
protected String preparedParam;
public BaseClass(String preparedParam) {
this.param = param;
}
}
class ChildClass {
public ChildClass (Map<String, Object> params) {
// need to work with params and prepare param for super constructor
super(param);
}
}
Run Code Online (Sandbox Code Playgroud) 我试图在Java中获得继承权,并且已经了解到当在子类中重写方法(和隐藏字段)时,仍然可以使用"super"关键字从超类中访问它们.
我想知道的是,'super'关键字是否应该用于非重写方法?
有没有区别(对于非重写方法/非隐藏字段)?
我在下面举了一个例子.
public class Vehicle {
private int tyreCost;
public Vehicle(int tyreCost) {
this.tyreCost = tyreCost;
}
public int getTyreCost() {
return tyreCost;
}
}
Run Code Online (Sandbox Code Playgroud)
和
public class Car extends Vehicle {
private int wheelCount;
public Vehicle(int tyreCost, int wheelCount) {
super(tyreCost);
this.wheelCount = wheelCount;
}
public int getTotalTyreReplacementCost() {
return getTyreCost() * wheelCount;
}
}
Run Code Online (Sandbox Code Playgroud)
具体来说,既然getTyreCost()没有被覆盖,应该getTotalTyreReplacementCost()使用getTyreCost(),还是super.getTyreCost()?
我想知道是否应该在访问超类的字段或方法的所有实例中使用super(在代码中显示您正在访问超类),或者仅在重写/隐藏的那些实例中使用super(因此它们脱颖而出).
我有一个基类:
class ViewController: UIViewController
{
init(nibName nibNameOrNil: String?)
{
super.init(nibName: nibNameOrNil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) { }
}
Run Code Online (Sandbox Code Playgroud)
子类:
class OneViewController: ViewController
{
private var one: One
init(one: One)
{
self.one = one
super.init(nibName: "OneNib")
}
required init?(coder aDecoder: NSCoder) { }
}
Run Code Online (Sandbox Code Playgroud)
以及上述子类的子类:
class TwoViewController: OneViewController
{
private var two: Two
init(two: Two)
{
self.two = two
super.init(nibName: "TwoNib") <== ERROR
}
required init?(coder aDecoder: NSCoder) { }
}
Run Code Online (Sandbox Code Playgroud)
在指定的行我得到错误:
Ambiguous reference to member 'init(one:)'
我不明白为什么编译器无法弄清楚我指的是 …
在调查这个问题时,我遇到了单一参数的奇怪行为super:
调用super(some_class).__init__()在some_class(或其子类)的方法内部工作,但在其他地方调用时抛出异常.
代码示例:
class A():
def __init__(self):
super(A).__init__() # doesn't throw exception
a = A()
super(A).__init__() # throws exception
Run Code Online (Sandbox Code Playgroud)
抛出的异常是
Traceback (most recent call last):
File "untitled.py", line 8, in <module>
super(A).__init__() # throws exception
RuntimeError: super(): no arguments
Run Code Online (Sandbox Code Playgroud)
我不明白为什么电话的位置有所不同.
众所周知,super 执行魔法的零参数形式:
零参数形式仅适用于类定义,因为编译器填写必要的细节以正确检索正在定义的类,以及访问普通方法的当前实例.
但是,对于单参数形式,没有这样的陈述super.反之:
另请注意,除零参数形式外,super()不限于使用内部方法.
所以,我的问题是,引擎盖下究竟发生了什么?这是预期的行为吗?
因为这个问题是关于继承的super,所以我们先写一个类.这是一个代表一个人的简单日常课程:
class Person:
def __init__(self, name):
super().__init__()
self.name = name
Run Code Online (Sandbox Code Playgroud)
像每个好类一样,它在初始化之前调用它的父构造函数.这个班级完美地完成了它的工作; 它可以毫无问题地使用:
>>> Person('Tom')
<__main__.Person object at 0x7f34eb54bf60>
Run Code Online (Sandbox Code Playgroud)
但是当我尝试创建一个继承自两个Person类和另一个类的类时,事情突然出现了:
class Horse:
def __init__(self, fur_color):
super().__init__()
self.fur_color = fur_color
class Centaur(Person, Horse):
def __init__(self, name, fur_color):
# ??? now what?
super().__init__(name) # throws TypeError: __init__() missing 1 required positional argument: 'fur_color'
Person.__init__(self, name) # throws the same error
Run Code Online (Sandbox Code Playgroud)
由于钻石继承(object顶部的类),因此无法Centaur正确初始化实例.将super().__init__()在Person结束了通话Horse.__init__,因为它抛出一个异常fur_color参数丢失.
但是如果Person和Horse不打电话,这个问题就不会存在super().__init__() …
尝试进行交叉兼容的订单保留QueryDict子类时:
from collections import OrderedDict
from django.http import QueryDict
from django.conf import settings
settings.configure()
class OrderedQueryDict(QueryDict, OrderedDict):
pass
querystring = 'z=33&x=11'
print(QueryDict(querystring).urlencode())
print(OrderedQueryDict(querystring).urlencode())
Run Code Online (Sandbox Code Playgroud)
在Python 3.x上输出(正确和预期的结果):
z=33&x=11 # or maybe x=11,z=33 on Python<=3.5
z=33&x=11
Run Code Online (Sandbox Code Playgroud)
在Python 2.7上的输出(此查询字符串已损坏):
x=11&z=33
z=3&z=3&x=1&x=1
Run Code Online (Sandbox Code Playgroud)
为什么这个想法在Python 3上有效,但在Python 2上无效?
Django v1.11.20。
python django dependency-injection multiple-inheritance super
super ×10
python ×7
django ×2
inheritance ×2
java ×2
python-3.x ×2
class ×1
coding-style ×1
constructor ×1
dictionary ×1
ios ×1
swift ×1
swift2 ×1