0

我有简单的装饰器,用于在尝试检索 dict 值时替换无效字符。

import types


class ContentInterface(dict):
    def __getitem__(self, item):
        raise NotImplementedError


class Content(ContentInterface):
    def __getitem__(self, item):
        return dict.__getitem__(self, item)


class DictDecorator(ContentInterface):
    def __init__(self, interfaceContent, **config):
        super(DictDecorator, self).__init__()
        self._component = interfaceContent
        self._config = config

    def _replace(self, text):
        return text

    def _check(self, invalidCharacterSet, itemPath):
        pass

    def __getitem__(self, name):
        item = self._component[name]
        if isinstance(item, types.StringTypes):
            newText = self._replace(item)
            invalidCharacterSet = set([char for char in item if char not in newText])
            self._check(invalidCharacterSet, name)
            return newText
        else:
            return self.__class__(item, **self._config)


class ReplaceCommaDecorator(DictDecorator):
    def _replace(self, text):
        return text.replace(",", ' ')


class ReplaceDotDecorator(DictDecorator):
    def _replace(self, text):
        return text.replace('.', ' ')


class ReplaceColonDecorator(DictDecorator):
    def _replace(self, text):
        return text.replace(":", ' ')


class ReplaceSemicolonDecorator(DictDecorator):
    def _replace(self, text):
        return text.replace(";", ' ')

我想通过以下方式使用它:

dictWithReplacedCharacters =\
ReplaceCommaDecorator(                       # Empty
    ReplaceDotDecorator(                     # Empty
        ReplaceColonDecorator(               # Empty
            ReplaceSemicolonDecorator(       # Empty
                Content({                    # Data
                    '1':u'1A:B;C,D.E',
                    '2':{
                        '21':u'21A:B;C,D.E',
                        '22':u'22A:B;C,D.E',
                    }
                }),
            ),
        ),
    ),
)

print dictWithReplacedCharacters['2']['21']

我有 4 个冗余 dict 对象代表一个数据字典的装饰器。

我想强制上面的嵌套语句返回 ReplaceCommaDecorator 对象继承自 ReplaceDotDecorator 继承自 ReplaceColonDecorator 继承自 ReplaceSemicolonDecorator 继承自包含数据的内容。我想这可以在 DictDecorator 的 __new__ 方法中解决。

4

1 回答 1

0

我不认为你在做什么是正确的方法。我只想写一个接受一组通用字符并正确检查/替换的类,所以如果你想转义更多字符,你必须简单地传递一个包含所有字符的集合(可能还有一些关于如何替换的元信息ETC。)。

在您的示例中,代码不起作用,因为str.replace需要两个参数,而您只传递一个。也许你想删除角色?在这种情况下,您应该这样做replace(character, "")。无论如何,如果你打算只用单个字符替换单个字符,那么你可以看看模块中的str.translate方法和maketrans功能string

否则,也许正则表达式是要走的路(使用re.sub)。

无论如何,做你要求的一种方法是:

class ContentInterface(dict):
    pass

class Content(ContentInterface):
    pass

class DictDecorator(ContentInterface):

    def __new__(cls, other):
        if isinstance(other, DictDecorator):
            if not issubclass(cls, other.__class__) and not issubclass(other.__class__, cls):
                new_cls = type('NewType', (cls, other.__class__), {})
                return new_cls(other)

        ob = dict.__new__(cls)
        return ob

    def __init__(self, interface, **config):
        super(DictDecorator, self).__init__()
        self._component = interface
        self._config = config

        # just to make the result appear with the content.
        # You may not need this.
        self.update(self._component)

    def _replace(self, text):
        return text

    def _check(self, invalid_char_set, item_path):
        pass

    def __getitem__(self, name):
        item = self._component[name]
        if isinstance(item, basestring):
            new_text = self._replace(item)
            invalid_char_set = set(char for char in item if char not in new_text)
            self._check(invalid_char_set, name)
            return new_text
        else:
            # What you wrote here does not make sense...
            # maybe you wanted: return self._config[name]?
            return super(DictDecorator, self).__getitem__(name)


class ReplaceCommaDecorator(DictDecorator):
    def _replace(self, text):
        return text.replace(",", ' ')


class ReplaceDotDecorator(DictDecorator):
    def _replace(self, text):
        return text.replace('.', ' ')


class ReplaceColonDecorator(DictDecorator):
    def _replace(self, text):
        return text.replace(":", ' ')


class ReplaceSemicolonDecorator(DictDecorator):
    def _replace(self, text):
        return text.replace(";", ' ')

它似乎有效:

>>> a = Content({'1': u'1A:B;C,D.E', '2': {'21': u'21A:B;C,D.E', '22': u'22A:B;C,D.E'}})
>>> r = ReplaceDotDecorator(ReplaceCommaDecorator(a))
>>> r['1']
u'1A:B;C D E'
>>> r = ReplaceColonDecorator(ReplaceDotDecorator(ReplaceCommaDecorator(a)))
>>> r['1']
u'1A B;C D E'

可能有更好的方法可以做到这一点,也许使用元类,但这是我能想到的唯一方法。

编辑:

顺便说一句,如果您不确切知道自己在做什么,我认为子类化内置类型并不是一个好主意:

>>> class MyDict(dict): pass
... 
>>> a = MyDict(a=1, b=2)
>>> a
{'a': 1, 'b': 2}
>>> a.__class__
<class '__main__.MyDict'>
>>> copy = a.copy()
>>> copy.__class__     # Wrong class.
<type 'dict'>

或者另一个例子:

>>> class MyDict(dict):
...     def __getitem__(self, key):
...             if key.startswith('a'):
...                     return 'BAD!'
...             return super(MyDict, self).__getitem__(key)
... 
>>> my = MyDict(a=1, b=2)
>>> my['a']
'BAD!'
>>> my['b']
2
>>> my.keys()
['a', 'b']
>>> my.values()   #you'd expect ['BAD!', 2]
[1, 2]

因此,请务必重新实现您将要使用的每种方法,这可能会导致类似的事情。

于 2012-09-05T11:04:37.397 回答