在Python 3.x中,super()可以不带参数调用:
class A(object):
def x(self):
print("Hey now")
class B(A):
def x(self):
super().x()
Run Code Online (Sandbox Code Playgroud)
>>> B().x()
Hey now
Run Code Online (Sandbox Code Playgroud)
为了使这项工作,一些编译时间魔法进行,其中的一个后果是,下面的代码(重新绑定super到super_)失败:
super_ = super
class A(object):
def x(self):
print("No flipping")
class B(A):
def x(self):
super_().x()
Run Code Online (Sandbox Code Playgroud)
>>> B().x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in x
RuntimeError: super(): __class__ cell not found
Run Code Online (Sandbox Code Playgroud)
super()如果没有编译器的帮助,为什么无法在运行时解析超类?是否存在这种行为或其潜在原因可能会让一个不知情的程序员陷入困境的实际情况?
...并且,作为一个附带问题:在Python中是否有任何其他函数,方法等示例可以通过将它们重新绑定到不同的名称来打破?
我有这样的代码:
class A(object):
def __init__(self):
self.a = 1
class B(A):
def __init__(self):
self.b = 2
super(self.__class__, self).__init__()
class C(B):
def __init__(self):
self.c = 3
super(self.__class__, self).__init__()
Run Code Online (Sandbox Code Playgroud)
实例化B按预期工作但实例化C无限递归并导致堆栈溢出.我怎么解决这个问题?
对Python进行子类化dict按预期工作:
>>> class DictSub(dict):
... def __init__(self):
... self[1] = 10
...
>>> DictSub()
{1: 10}
Run Code Online (Sandbox Code Playgroud)
但是,用a做同样的事情是collections.OrderedDict行不通的:
>>> import collections
>>> class OrdDictSub(collections.OrderedDict):
... def __init__(self):
... self[1] = 10
...
>>> OrdDictSub()
(…)
AttributeError: 'OrdDictSub' object has no attribute '_OrderedDict__root'
Run Code Online (Sandbox Code Playgroud)
因此,OrderedDict实现使用私有__root属性,这可以防止子类OrdDictSub的行为类似于DictSub子类.为什么?如何从OrderedDict继承?
这里是 Python 3,以防万一它很重要。
我试图正确理解如何在@property使用时实现继承,并且我已经搜索了 StackOverflow 并阅读了 20 个类似的问题,但无济于事,因为他们试图解决的问题略有不同。这是我用于测试的代码:
class Example:
def __init__(self):
self.__data = None
@property
def data(self):
return self.__data
@data.setter
def data(self, data):
self.__data = data
class Example2(Example):
def __init__(self):
super().__init__()
@property
def data(self):
return super().data # Works!
@data.setter
def data(self, data):
data = '2' + data
#Example.data = data # Works, but I want to avoid using the parent name explicitly
#super().data = data # Raises AttributeError: 'super' object has no attribute 'data'
#super().data.fset(self, data) # …Run Code Online (Sandbox Code Playgroud) 这是我试图编写的代码:
class A(object):
def bind_foo(self):
old_foo = self.foo
def new_foo():
old_foo()
#super().foo()
super(self.__class__,self).foo()
self.foo = new_foo
def __init__(self):
print("A __init__")
def foo(self):
print("A foo")
class B(A):
def __init__(self):
print("B __init__")
super().__init__()
def foo(self):
print("B foo")
super().foo()
class C(A):
def __init__(self):
print("C __init__")
super().__init__()
super().bind_foo()
def foo(self):
print("C foo")
b = B()
b.foo()
c = C()
c.foo()
Run Code Online (Sandbox Code Playgroud)
B类和A类是预期的行为,也就是说,当我打电话时b.foo(),它a.foo()也会调用super().C类是试图模仿孩子B和父A行为,但这次我不想明确地super().foo()放在子类中,但我仍然想要父类foo()调用.它按预期工作.
然而,我不太明白的是A.bind_foo,我必须使用super(self.__class__,self).foo()而不是super().foo.super().foo给了一个
"SystemError: super(): no arguments". …Run Code Online (Sandbox Code Playgroud) 我正在运行Django 1.4.11.我save()以类似于以下代码的方式覆盖Django模型的方法:
from django.db import models
from django.db import transaction
class MyModel(models.Model):
# model definition
@transaction.commit_manually
def save(self, *args, **kwargs):
try:
super(self.__class__, self).save(*args, **kwargs)
foo() # do_other_things
except:
transaction.rollback()
raise
else:
transaction.commit()
Run Code Online (Sandbox Code Playgroud)
当我运行我的代码时,有时我会在Apache日志中阅读此消息:
RemovedInDjango18Warning:commit_manually已弃用,支持set_autocommit.
如何使用set_autocommit实现相同的逻辑?
python ×6
inheritance ×3
super ×3
python-3.x ×2
class ×1
django ×1
oop ×1
overriding ×1
subclass ×1