请考虑以下代码:
class A(object):
attr = None
def __init__(self):
assert A.attr is not None
class B(object):
def __init__(self, attr):
A.attr = attr
class C(A):
def __init__(self):
super().__init__()
class D(A):
def __init__(self):
super().__init__()
nested_classes = {cls.__name__: cls for cls in {C, D}}
以上似乎没有按照我的意图行事,因为:
>>> first_class = B("first")
>>> first_sub_class = first_class.C()
>>> first_sub_class.attr
'first'
>>> second_class = B("second")
>>> second_sub_class = second_class.C()
>>> second_sub_class.attr
'second'
>>> first_sub_class.attr
'second'
first_sub_class.attr
成为first
时,second_sub_class.attr
是否有second
?可能有一个范围在B范围内的元类?
几点:
attr
,我想在B初始化时设置它。partial
环绕上述点,因为它打破了依赖于__name__
或__qualname__
或类似的其余代码。答案 0 :(得分:1)
要解决此问题,只需在self.attr = self.attr
__init__
函数中添加第A
行。由于您不想更改A
的属性,因此您必须进行以下更改:
class A(object):
attr = None
def __init__(self):
assert self.attr is not None # Don't refer to A, but to self to get the correct value
self.attr = self.attr
class B(object):
def __init__(self, attr):
self.attr = attr # Don't edit A, just save the value in own instance
def __getattribute__(self, item): # completely added, does some magic to ensure class.attr is set correctly
if item in B.nested_classes:
c = B.nested_classes[item]
c.attr = self.attr
return c
return super().__getattribute__(item)
class C(A):
def __init__(self):
super().__init__()
class D(A):
def __init__(self):
super().__init__()
nested_classes = {cls.__name__: cls for cls in {C, D}}
first_class = B("first")
first_sub_class = first_class.C()
print(first_sub_class.attr)
second_class = B("second")
second_sub_class = second_class.C()
print(second_sub_class.attr)
print(first_sub_class.attr)
答案 1 :(得分:1)
你疯狂地过度复杂了:
class A:
def __init__(self, attr):
self.attr = attr
class C(A):
pass
class D(A):
pass
class B:
def __init__(self, attr):
self.attr = attr
def C(self):
return C(self.attr)
def D(self):
return D(self.attr)
完全符合要求:
>>> first_class = B("first")
>>> first_sub_class = first_class.C()
>>> first_sub_class.attr
'first'
>>> second_class = B("second")
>>> second_sub_class = second_class.C()
>>> second_sub_class.attr
'second'
>>> first_sub_class.attr
'first'