Decorator动态超类

2024-09-24 22:28:03 发布

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

当试图检索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对象代表一个数据dict的装饰器

我想强制上面的嵌套语句返回从ReplaceDotDecorator继承的ReplaceCommaDecorator对象,ReplaceDotDecorator继承自replaceColondecocorator,replaceComolondecocorator继承自包含数据的内容。我想这可以用DictDecorator的新方法来解决。你知道吗


Tags: textselfconfigreturndefitemdictreplace
1条回答
网友
1楼 · 发布于 2024-09-24 22:28:03

我认为你的做法不对。我只需要编写一个类来接受一组通用字符,并正确地进行检查/替换,因此如果您想转义更多的字符,只需传递一个包含所有字符的集合(可能还需要一些关于如何替换等的元信息)。你知道吗

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

否则,regex可能是一种方法(使用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]

所以一定要重新实现你将要使用的每个方法,这可能会导致类似的事情。你知道吗

相关问题 更多 >