Python 使用Super设置父类属性
可以在Python2.7中使用super设置父类属性吗?我希望以下代码能够正常工作,但它不能:Python 使用Super设置父类属性,python,python-2.7,Python,Python 2.7,可以在Python2.7中使用super设置父类属性吗?我希望以下代码能够正常工作,但它不能: class A(object): val_a = 1 class B(A): val_b = 2 def set_a(self, val): super(B,self).__class__.val_a = val b = B() b.set_a(3) 它给出了以下错误: TypeError: can't set attributes of built-
class A(object):
val_a = 1
class B(A):
val_b = 2
def set_a(self, val):
super(B,self).__class__.val_a = val
b = B()
b.set_a(3)
它给出了以下错误:
TypeError: can't set attributes of built-in/extension type 'super'
有正确的方法吗?根据您的代码,您正在尝试对实例进行更改。然后,函数集_a需要如下所示
class B(A):
val_b = 2
def set_a(self, val):
self.val_a = val
但是如果您需要更改以适用于类级别,则可以使用类方法,而不能使用超级方法
会回来的
五,
五,
直接引用A.val_A。在本例中,val_a是一个静态变量,而不是对象实例的属性
super调用试图获取self instance的对象,因此访问属性superB、self.val_a将失败
class A(object):
val_a = 1
class B(A):
val_b = 2
def set_a(self, val):
A.val_a = val
b = B()
b.set_a(3)
print b.val_a
可以在python 2.7中使用super设置静态类属性吗
没有
我希望下面的代码能够工作,但它不能
首先,_类_实际上由super进行特殊大小写,以返回super实例的类,而不是执行通常由super执行的MRO搜索
第二,没有B。超级要绕过的条目,所以即使“类”不是特例,它仍然是B而不是A
第三,如果你想特别提到A类,而不是self的MRO中接下来发生的任何事情,你应该直接提到A类
长话短说:使用A,而不是超级。请参阅
您不能用super来完成,但您可以搜索子类的基类并以这种方式完成
我的意思是:
class Other(object):
val_a = 42
class A(Other):
val_x = 1
def __str__(self):
return '{}(val_a={})'.format(self.__class__.__name__, self.val_a)
class B(A):
val_b = 2
def set_a(self, val):
for cls in self.__class__.__mro__[1:]:
try:
object.__getattribute__(cls, 'val_a')
except AttributeError:
continue
print('Updating class: {}'.format(cls.__name__))
cls.val_a = val
break
else:
raise RuntimeError("Can't find a base class with attribute 'val_a'")
b = B()
print(b) # -> B(val_a=1) # B(val_a=42)
print('Other.val_a: {}'.format(Other.val_a)) # Other.val_a: 42
print('A.val_a: {}'.format(A.val_a)) # A.val_a: 42
print('B.val_a: {}'.format(B.val_a)) # B.val_a: 42
print('')
b.set_a(3) # Updating class: Other
print('')
print(b) # B(val_a=3)
print('Other.val_a: {}'.format(Other.val_a)) # Other.val_a: 3
print('A.val_a: {}'.format(A.val_a)) # A.val_a: 3
print('B.val_a: {}'.format(B.val_a)) # B.val_a: 3
你应该去上这门课而不是这门课。super.\uuuuu class\uuuuuuu是super对象的类属性,而super.\uuuuu thisclass\uuuuu是父类的类属性。@Faibbus,我刚刚用\uuuuuu thisclass\uuuuu替换了\uuuuuuuuu class\uuuuuuuuu,效果不错。谢谢我想知道为什么会这样?你为什么要这么做?B继承自A,B的任何实例都可以访问A的属性。你应该在self上设置值。@Faibbus:那是B,不是A。看起来提问者想要A。@Faibbus:是的,但是superA,self。u这个类是编写A的一种非常复杂的方式,没有任何好处。不,对不起。这只会为特定实例设置val_a的值。我想为类A设置它。但是根据您的代码,函数不是类方法,那么它只适用于特定实例。如果你想为类设置变量,set_a需要是一个类方法。这是对你的问题的回答,你可以用super设置静态类属性吗?否则,你可以编辑你的问题,让它更清楚,如果你想让方法为类设置变量。谢谢你的建议。我已经编辑了标题和问题,以使意图更加明确。谢谢你的答复。Faibbus建议将uu this class_uu与super一起使用,实际上似乎确实有效。@p提示:那是B。如果你想分配给B.val_ua,你应该直接分配给B.val_ua,而不是绕着super走弯路。不过,听起来你想分配给A.val_A。你说得对,谢谢——我没听清楚。我想我将只使用A.val_A。通过b设置A的静态属性的值是,这样我就有了一个一致的接口;我什么都可以用b。谢谢你的回答。不幸的是,正如Faibbus的建议一样,这只改变了B类的属性,而不是A类。typeself与使用self没有什么不同。据我所知,1。typeself与使用self没有什么不同,但是看起来更好。。这取决于应用程序。假设您不想弄乱类A名称空间,并且设置了一个在类A中定义的方法。在这种情况下,您可以使用此解决方案。谢谢,这是一个非常好的解决方案。也许比我需要的更复杂。如果你知道只有一个基类,你可以硬编码,无条件地使用self。uuu class_uuu。uuu mro_uu[1]。val\u a=val.hasattrcls,“val\u a”不关心属性是否在类cls中实际定义;它将拾取继承的属性。这个错误在这里不可见,只是因为val_a在MRO的下一个类中定义了。@user2357112:很好,我想我已经在修改后的答案中解决了这个问题。它现在工作得更好了,但不是出于好的原因,也可能不是出于你所想的原因。cls.\uuuuu getattribute\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。碰巧这通常是对象。它不知道如何搜索cls的MRO。如果涉及到另一个uuu getattribute uuuuuu方法,情况就不一样了。使用super的主要原因之一是避免将[base]类名硬编码到子类的代码中。
class A(object):
val_a = 1
class B(A):
val_b = 2
def set_a(self, val):
type(self).val_a = val
b1 = B()
b1.set_a(3)
b2 = B()
b2.set_a(4)
print type(b1).val_a
print type(b2).val_a
print A.val_a
print B.val_a
class Other(object):
val_a = 42
class A(Other):
val_x = 1
def __str__(self):
return '{}(val_a={})'.format(self.__class__.__name__, self.val_a)
class B(A):
val_b = 2
def set_a(self, val):
for cls in self.__class__.__mro__[1:]:
try:
object.__getattribute__(cls, 'val_a')
except AttributeError:
continue
print('Updating class: {}'.format(cls.__name__))
cls.val_a = val
break
else:
raise RuntimeError("Can't find a base class with attribute 'val_a'")
b = B()
print(b) # -> B(val_a=1) # B(val_a=42)
print('Other.val_a: {}'.format(Other.val_a)) # Other.val_a: 42
print('A.val_a: {}'.format(A.val_a)) # A.val_a: 42
print('B.val_a: {}'.format(B.val_a)) # B.val_a: 42
print('')
b.set_a(3) # Updating class: Other
print('')
print(b) # B(val_a=3)
print('Other.val_a: {}'.format(Other.val_a)) # Other.val_a: 3
print('A.val_a: {}'.format(A.val_a)) # A.val_a: 3
print('B.val_a: {}'.format(B.val_a)) # B.val_a: 3