python中兩個屬相相關方法python
result = obj.name 會調用builtin函數getattr(obj,'name')查找對應屬性,若是沒有name屬性則調用obj.__getattr__('name')方法,再無則報錯函數
obj.name = value 會調用builtin函數setattr(obj,'name',value)設置對應屬性,若是設置了__setattr__('name',value)方法則優先調用此方法,而非直接將值存入__dict__並新建屬性ui
nn.Module中實現了__setattr__()方法,當再class的初始化__init__()中執行module.name=value時,會在其中判斷value是否屬於Parameters或者nn.Module對象,是則將之存儲進入__dict__._parameters和__dict__._modules兩個字典中;若是是其餘對象諸如Variable、List、dict等等,則調用默認操做,將值直接存入__dict__中。對象
nn.Module的新建Parameter屬性,在._parameters中能夠查詢到,在.__dict__中沒有,屬於.__dict__._parameters中blog
import torch as t import torch.nn as nn module = nn.Module() module.param = nn.Parameter(t.ones(2,2)) print(module._parameters) """ OrderedDict([('param', Parameter containing: 1 1 1 1 [torch.FloatTensor of size 2x2])]) """ print(module.__dict__) """ {'_backend': <torch.nn.backends.thnn.THNNFunctionBackend at 0x7f5dbcf8c160>, '_backward_hooks': OrderedDict(), '_buffers': OrderedDict(), '_forward_hooks': OrderedDict(), '_forward_pre_hooks': OrderedDict(), '_modules': OrderedDict(), '_parameters': OrderedDict([('param', Parameter containing: 1 1 1 1 [torch.FloatTensor of size 2x2])]), 'training': True} """
以一般List的格式傳入的子Module直接從屬於屬於.__dict__,並未被_modules識別ip
submodule1 = nn.Linear(2,2) submodule2 = nn.Linear(2,2) module_list = [submodule1,submodule2] module.submodules = module_list print('_modules:',module_list) # _modules: [Linear (2 -> 2), Linear (2 -> 2)] print('__dict__[submodules]:',module.__dict__.get('submodules')) # __dict__[submodules]: [Linear (2 -> 2), Linear (2 -> 2)] print('__dict__[submodules]:',module.__dict__['submodules']) # __dict__[submodules]: [Linear (2 -> 2), Linear (2 -> 2)]
以ModuleList格式傳入的子Module可被._modules識別,而不直接從屬於.__dict__get
module_list = nn.ModuleList(module_list) module.submodules = module_list print(isinstance(module_list,nn.Module)) # True print(module._modules) """ OrderedDict([('submodules', ModuleList ( (0): Linear (2 -> 2) (1): Linear (2 -> 2) ))]) """ print(module.__dict__.get('submodules')) # None print(module.__dict__['submodules']) """ --------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-19-d4344afabcbf> in <module>() ----> 1 print(module.__dict__['submodules']) KeyError: 'submodules' """
nn.Module的.__getattr__()方法會對__dict__._module、__dict__._parameters和__dict__._buffers這三個字典中的key進行查詢。當nn.Module進行屬性查詢時,會先在__dict__進行查詢(僅查詢本級),查詢不到對應屬性值時,就會調用.__getattr__()方法,再無結果就報錯。input
對於__dict__中的屬性.training,能夠看到.__getattr__('training')查詢時就沒有結果,it
print(module.__dict__.get('submodules')) # None getattr(module,'training') # True module.training # True module.__getattr__('training') """ --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) …… AttributeError: 'Module' object has no attribute 'training' """
另外,咱們能夠看到.__getattr__能夠查詢到的結果以下,都是nn.Module自建的屬性,io
module.__getattr__ """ <bound method Module.__getattr__ of Module ( (submodules): ModuleList ( (0): Linear (2 -> 2) (1): Linear (2 -> 2) ) )> """
對於普通的新建屬性,其實和nn.Module自建的沒什麼不一樣,不一樣查詢方式輸出類似,
module.attr1 = 2 getattr(module,'attr1') # 2 module.__getattr__('attr1') """ --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) …… AttributeError: 'Module' object has no attribute 'attr1' """
對於nn.Module的特殊屬性,能夠看到,getattr和.__getattr__都可查到,這也是因爲getattr一次查找無果後,調用.__getattr__的結果,
getattr(module,'param') """ Parameter containing: 1 1 1 1 [torch.FloatTensor of size 2x2] """ module.__getattr__('param') """ Parameter containing: 1 1 1 1 [torch.FloatTensor of size 2x2] """