这就是我正在尝试的
# This is how I understood composition to work
class A():
def __init__(self):
self.attr1 = ''
self.attr2 = 0
self.attr3 = ''
def some_update(self, newval):
self.attr3 = newval
class B():
def __init__(self):
self.attr4 = ''
self.sub1 = A()
self.sub2 = A()
self.sub2.attr1 = subspecialval
def different_update(self, newval1, newval2)
self.sub1.attr2 = newval1
self.sub2.attr2 = newval2
def __main__():
my_obj = B()
B.sub1.attr = 'some string' # This doesn't work
setattr(B, 'sub1.attr1', 'some string') # This works
print(B.sub1.attr1) # This doesn't work
print(getattr(B, 'sub1.attr1')) # This works
if __name__ == '__main__':
main()
问题是,为什么点表示法不扩展到组合类(B),但是getattr / setattr能够正确协商类继承关系?我以为每个点都将延伸到层次结构中的下一个对象级别,但是它似乎无法正常工作
答案 0 :(得分:1)
getattr / setattr能够正确协商类层次结构吗?
不是。
setattr(B, 'sub1.attr1', 'some string')
设置文字属性'sub1.attr1'
。什么都没有遍历或协商。
请记住,您是在类(B
)而不是实例(my_obj
)上设置属性。 my_obj.sub1.attr
就可以了。
class A:
def __init__(self):
self.attr2 = ''
class B:
def __init__(self):
self.a = A()
B.a.attr1 = ''
AttributeError: type object 'B' has no attribute 'a'
另一方面,
b = B()
b.a.attr1 = 'attr1'
print(b.a.attr1)
工作。
setattr(B, 'a.attr1', 'new')
在做什么?
它在'a.attr1
类自身上设置文字属性B
。一切都不必动摇或协商。
setattr(B, 'a.attr1', 'new')
print(B.__dict__)
输出
{'__module__': '__main__', '__init__': <function B.__init__ at 0x00000188F1EB9F28>,
'__dict__': <attribute '__dict__' of 'B' objects>,
'__weakref__': <attribute '__weakref__' of 'B' objects>, '__doc__': None,
'a.attr1': 'new'}
答案 1 :(得分:0)
您对类和python有基本的误解。
B.sub1.attr = 'some string'
不起作用 B
是类型<class 'B'>
。类型sub1
中没有属性B
。
我相信您期望使用类型<class 'A'>
,可以通过在类级别定义该属性来实现:
>>> class A:
... pass
...
>>> class B:
... sub1 = A()
...
>>> B.sub1
<__main__.A object at 0x7fa2e1d1c490>
奇怪的是,同样的sub1
也可用作实例属性。如果您和我一样,那是python中的错误,请打开讨论。
>>> b = B()
>>> b.sub1
<__main__.A object at 0x7fa2e1d1c490>
setattr(B, 'sub1.attr1', 'some string')
有效 setattr
将始终有效。它强制属性可用。它在类对象中创建属性。
B.sub1.attr1
不起作用。 getattr(B, 'sub1.attr1')
确实这是最奇怪的,我也不知道。归结为对setattr(B, 'sub1.attr1', 'some string')
的调用。如前所述,强制使用属性。
我认为正在发生的事情是您无法通过python语法访问该属性,因为该属性名称实际上包含一个点sub1.attr1
。但是您可以将原始字符串作为属性名称传递给getattr
,这就是它起作用的原因。
在这种情况下,您可能想做的就是将属性设置为类'A'的实例。
>>> class A:
... def __init__(self):
... self.attr1 = 'attr A'
...
>>> class B:
... pass
...
>>> setattr(B, 'sub1', A())
>>> B.sub1.attr1
'attr A'
但是到那时属性sub1.attr1
不存在!
>>> getattr(B, 'sub1.attr1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'B' has no attribute 'sub1.attr1'
您正在使用内置函数getattr
和setattr
做一些非常奇怪的事情。如果您正在学习,那很好,但是请注意,它需要了解语言中正在发生的事情才能成功使用此类功能。
有了足够的魔力,属性名称实际上可以有.
个。