Python 在类中使用_setattr__控制属性索引的设置
如果我有:Python 在类中使用_setattr__控制属性索引的设置,python,python-3.x,Python,Python 3.x,如果我有: class myclass(): def __init__(self, x, list): self.x = x self.list = list def __setattr__(self, name, value): self.__dict__[name] = value #some stuff 你呢 instance = myclass(3, ['a', 'b']) instance.x = 5
class myclass():
def __init__(self, x, list):
self.x = x
self.list = list
def __setattr__(self, name, value):
self.__dict__[name] = value
#some stuff
你呢
instance = myclass(3, ['a', 'b'])
instance.x = 5
instance.list[1] = 'c'
将为第一个而不是第二个调用_usetattr _uu方法,因为只设置属性的索引而不是属性
是否有任何方法可以控制当属性列表的索引发生更改时会发生什么,或者以这种方式将列表作为属性只是一种不好的做法?以下是一个示例,它可以满足您的需要:
import re
def c_set_port_state(portn,ports,values):
print(portn,ports,values)
class Out:
def __init__(self, obj):
self.obj = obj
def __getitem__(self, i):
return self.obj._out[i]
def __setitem__(self, i, value):
self.obj._out[i] = value
self.obj.set_out({i:value})
class In:
def __init__(self, obj):
self.obj = obj
def __getitem__(self, i):
return self.obj.get_in(i)
def _outidx0(key):
idx = re.match(r'Out(\d)',key).group(1)
idx0 = int(idx)-1
return idx0
class _port_descriptor:
def __init__(self, name):
self.name = name
self.idx0 = _outidx0(name)
def __get__(self, obj, objtype):
return obj.Out[self.idx0]
def __set__(self, obj, value):
obj.Out[self.idx0] = value
class Ports:
"""
This is an example for dynamic attibutes
- that figure in dir() and
- that IPython can auto-complete
>>> ports = Ports()
>>> ports.Out3=0
1 dict_keys([2]) dict_values([0])
>>> ports.Out4=1
1 dict_keys([3]) dict_values([1])
>>> dir(ports) # doctest: +ELLIPSIS
['In', 'Out', 'Out1', 'Out2', 'Out3', 'Out4', 'Out5', 'Out6', 'Out7', 'Out8', ...
>>> ports.set_out(Out7=3) # doctest: +ELLIPSIS
Traceback (most recent call last):
...
ValueError: Output ...
>>> ports.Out7=3 # doctest: +ELLIPSIS
Traceback (most recent call last):
...
ValueError: Output ...
>>> ports.set_out(Out7=0)
1 dict_keys([6]) dict_values([0])
>>> ports.set_out({0:0,1:0,2:1})
3 dict_keys([0, 1, 2]) dict_values([0, 0, 1])
>>> ports.Out[2]
1
>>> ports.Out[2] = 0
1 dict_keys([2]) dict_values([0])
>>> ports.In[1]
0
"""
def __init__(self):
self._out = dict((i,0) for i in range(8))
self.Out = Out(self)
self.In = In(self)
for i in range(8):
name = 'Out'+str(i+1)
pd = _port_descriptor(name)
setattr(self.__class__,name,pd)
def set_out(self, out=None, **kwargs):
if out:
self._out.update(out)
if kwargs:
out = {_outidx0(k):v for k,v in kwargs.items()}
if not out:
out = self._out
if any((value not in [0,1]) for value in out.values()):
raise ValueError('Output values can only be 0 or 1, but you provided ' + str(out))
c_set_port_state(len(out),out.keys(),out.values())
def get_in(self, i):
return 0 #would call an according c function, too
旁注:使用
list
作为名称是不好的做法。调用变量列表可能是个坏主意,您的最终目标是什么?另外,您也不会使用defWell创建类。。。它是一个实例属性,因此没有真正的理由不能将其用作名称(除了编辑器的语法highlighter可能会混淆…)使用普通列表无法实现这一点,您需要创建集合的子类。MutableSequence
并在那里进行处理…列表仅用作示例。