使用 __setattr__ 在类中控制属性索引的设定

2024-03-29 09:11:08 发布

您现在位置:Python中文网/ 问答频道 /正文

如果我有:

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'

将为第一个方法而不是第二个方法调用\uuu setattr\uu方法,因为只设置属性的索引而不是属性

当属性列表的索引被更改时,有没有什么方法来控制发生了什么?或者以这种方式将列表作为属性只是一种不好的做法?你知道吗


Tags: 方法instancenameself列表属性initvalue
1条回答
网友
1楼 · 发布于 2024-03-29 09:11:08

下面是一个可以做你想做的事情的例子:

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

相关问题 更多 >