【发布时间】:2014-03-07 19:54:09
【问题描述】:
我正在编写的程序有问题,我终其一生都无法弄清楚我做错了什么。 好的,所以基本上我正在编写一个程序来从 XML 文档中提取数据并使用数据的类表示进行操作。
现在,我的程序增加了一些复杂性,因为我想变得聪明并使用描述符(我正在了解它们并认为我会尝试将它们集成到我的代码中)
注意:我将问题简化为可以按原样运行的自包含 python 脚本:
#!/usr/bin/env python
import inspect
class Numberise(object):
def __init__(self, value=0, base=16):
self.base = base
self.value = value
def __get__(self, obj, objtype):
return self.value
def __set__(self, obj, val):
#self.value = self.extract_number(val)
self.value = val
print 'set value to:', self.value
class Register(object):
width = Numberise(base=10)
def __init__(self, width=16, name='unNamed'):
super(Register, self).__init__()
tuple_args = inspect.getargvalues(inspect.currentframe()) #shorthand
for arg in tuple_args[0]:
setattr(self, arg, tuple_args[3][arg])
if __name__ == "__main__":
new_regs = [Register(width=i) for i in range(10)]
for i,reg in enumerate(new_regs):
reg.width = i
for R in new_regs:
print 'In extract(). Id:%s name:%s, width:%d'%(id(R), R.name, R.width)
当我运行脚本时,我得到以下输出:
C:\Users\gkuhn\Desktop>python test.py
set value to: 0
set value to: 1
set value to: 2
set value to: 3
set value to: 4
set value to: 5
set value to: 6
set value to: 7
set value to: 8
set value to: 9
set value to: 0
set value to: 1
set value to: 2
set value to: 3
set value to: 4
set value to: 5
set value to: 6
set value to: 7
set value to: 8
set value to: 9
In extract(). Id:48851280 name:unNamed, width:9
In extract(). Id:48852080 name:unNamed, width:9
In extract(). Id:48879472 name:unNamed, width:9
In extract(). Id:49285200 name:unNamed, width:9
In extract(). Id:49291504 name:unNamed, width:9
In extract(). Id:49291984 name:unNamed, width:9
In extract(). Id:49292016 name:unNamed, width:9
In extract(). Id:49292048 name:unNamed, width:9
In extract(). Id:49292080 name:unNamed, width:9
In extract(). Id:49292112 name:unNamed, width:9
我想要的是将宽度值 放在我制作的每个寄存器对象中。看起来它正在被共享。他们不应该是个体的吗?!
以下是我最初的问题,您不需要阅读它,但我还是把它留在这里了。实际问题已经讨论过了。
所以在下面的 sn-p 中,我基本上是在抓取我新创建的 Register 对象并将它们添加到已经创建的列表中。
self.regs = []
temps = []
for register in self.ip_root:
unrolled_regs = UnrollRegister(register)
new_regs = unrolled_regs.convert()
for R in new_regs:
#print 'In extract(). Id:%s name:%s, width:%d'%(id(R), R.name, R.width)
if 'extended' in R.name.lower():
print 'In extract(). Id:%s name:%s, width:%d'%(id(R), R.name, R.width)
temps.append(R)
#print 'In extract(). Id:%s name:%s, width:%d'%(id(R), R.name, R.width)
a = copy.deepcopy(R)
#print type(R).__dict__
#print temps
#self.regs.extend(new_regs)
self.regs += new_regs
#self.regs.extend(unrolled_regs.convert())
for n in temps:
print '\tIn loop. Id:%s name:%s, width:%d'%(id(n), n.name, n.width)
#print type(n).__dict__
对不起,我一直在努力解决这个问题!
Register 类的定义是:
class Register(Base):
width = Numberise(base=10)
address = Numberise(base=10)
def __init__(self, name='unNamed', width=16, description='No description provided',
access='RW', address=0, visibility='Public', reset='async',
documentation=''):
super(Register, self).__init__()
tuple_args = inspect.getargvalues(inspect.currentframe()) #shorthand
for arg in tuple_args[0]:
setattr(self, arg, tuple_args[3][arg])
self.bitfields = []
如前所述,我将数据描述符用于宽度和地址属性。 Numberise 描述符的定义是:
class Numberise(Base):
def __init__(self, value=0, base=16):
self.base = base
self.value = self.extract_number(value)
def __get__(self, obj, objtype):
return self.value
def __set__(self, obj, val):
self.value = self.extract_number(val)
def extract_number(self,input):
"try and get the value being represented"
if type(input) == int: #its already a number
return input
else: #its a string
RE = re.compile(r"\d?'([hHdDbB])(\w+)") #of the form 'h10 (verilog)
result = RE.search(input)
if result is not None:
radix, string_num = result.groups()
return int(string_num, {'h':16, 'd':10, 'b':2}[radix.lower()])
else:
return int(input, self.base)
Base 包含的内容不多,为了清楚起见,我将其包含在此处:
class Base(object):
def __init__(self):
self._parent_spacer = ''
self._spacer = '\t'
@property
def parent_spacer(self):
return self._parent_spacer
@parent_spacer.setter
def parent_spacer(self, value):
self._parent_spacer = value
@property
def spacer(self):
return self.parent_spacer+'\t'
这个描述符背后的想法是确保无论我们初始化宽度和地址属性是什么,保存的值总是整数而不是字符串。
现在是运行代码后所有重要的输出:
In extract(). Id:239825680 name:ASIC_ADC_RESULTS_EXTENDED_READ, width:64
In extract(). Id:239779088 name:ASIC_HART_EXTENDED_RECEIVE_BUFFER, width:64
In loop. Id:239825680 name:ASIC_ADC_RESULTS_EXTENDED_READ, width:16
In loop. Id:239779088 name:ASIC_HART_EXTENDED_RECEIVE_BUFFER, width:16
谁能拯救我的理智并向我解释这种行为?!
【问题讨论】:
-
您能否详细说明“这种行为”的含义?你期待看到什么?
标签: python attributes descriptor