代码之家  ›  专栏  ›  技术社区  ›  kindall

如何创建一个类似字符串的类?

  •  3
  • kindall  · 技术社区  · 14 年前

    with 陈述。此上下文管理器生成一个自定义结果对象,当块完成执行时,该对象将包含捕获的输出。

    from contextlib import contextmanager
    
    @contextmanager
    def capturing():
        "Captures output within a 'with' block."
        from cStringIO import StringIO
    
        class result(object):
            def __init__(self):
                self._result = None
            def __str__(self):
                return self._result
    
        try:
            stringio = StringIO()
            out, err, sys.stdout, sys.stderr = sys.stdout, sys.stderr, stringio, stringio
            output = result()
            yield output
        finally:
            output._result, sys.stdout, sys.stderr = stringio.getvalue(), out, err
            stringio.close()
    
    with capturing() as text:
        print "foo bar baz",
    
    print str(text)   # prints "foo bar baz"
    

    具有 str (我还把对象作为一种语法糖来调用)。

    因此,是否可以使结果实例像字符串一样工作,因为它在命名时实际上返回了一个字符串?我试着实施 __get__ ,但这似乎只对属性起作用。或者我想做的是真的不可能的?

    5 回复  |  直到 14 年前
        1
  •  4
  •   DevPlayer    12 年前

    如何创建一个类似字符串的类? 子类

    import os
    class LikeAStr(str):
        '''Making a class like a str object; or more precisely
        making a str subclass with added contextmanager functionality.'''
    
        def __init__(self, diff_directory):
            self._iwd = os.getcwd()
            self._cwd = diff_directory
    
        def __enter__(self):
            return self
    
        def __exit__(self, ext_typ, exc_value, traceback):
            try: os.chdir(self._iwd) # might get deleted within the "with" statement
            except: pass
    
        def __str__(self):
            return self._cwd
    
        def __repr__(self):
            return repr(self._cwd)
    
    
    astr = LikeAStr('C:\\')
    
    with LikeAStr('C:\\') as astr:
        print 1, os.getcwd()
        os.chdir( astr ) # expects str() or unicode() not some other class
        print 2, os.getcwd()
        #
    
    # out of with block
    print 3, os.getcwd()
    print 4, astr == 'C:\\'
    

    1 D:\Projects\Python\
    2 C:\
    3 D:\Projects\Python\
    4 True
    
        2
  •  2
  •   unutbu    14 年前

    我不相信有 清洁的 做你想做的事。 text globals() 听写。 您必须在 capturing 对象:

    如果您尝试使用 with 文本

    import sys
    import cStringIO
    
    class capturing(object):
        def __init__(self,varname):
            self.varname=varname
        def __enter__(self):
            self.stringio=cStringIO.StringIO()
            self.out, sys.stdout = sys.stdout, self.stringio
            self.err, sys.stderr = sys.stderr, self.stringio        
            return self
        def __exit__(self,ext_type,exc_value,traceback):
            sys.stdout = self.out
            sys.stderr = self.err
            self._result = self.stringio.getvalue()
            globals()[self.varname]=self._result
        def __str__(self):
            return self._result
    
    
    with capturing('text') as text:
        print("foo bar baz")
    
    print(text)   # prints "foo bar baz"
    # foo bar baz
    
    print(repr(text))
    # 'foo bar baz\n'
    
        3
  •  2
  •   kindall    11 年前

    乍一看,它看起来像 UserString (实际上 MutableString 足够地 就像一个字符串;我刚收到一些奇怪的格式 print str 串。(如果不是“真正的”字符串或其他东西,则会打印一个额外的空格。)我创建了一个玩具类来处理包装字符串的问题。我没有花时间找出原因,但看起来 是最有用的例子。

    bytearray 因为它在大多数情况下都像字符串一样工作,但是是可变的。我还写了一个单独的版本 splitlines() 将文本放入列表中。这非常有效,实际上对于我的即时用例来说更好,它正在删除各种函数的连接输出中的“额外”空行。这个版本是:

    import sys
    from contextlib import contextmanager
    
    @contextmanager
    def capturinglines(output=None):
        "Captures lines of output to a list."
        from cStringIO import StringIO
    
        try:
            output = [] if output is None else output
            stringio = StringIO()
            out, err = sys.stdout, sys.stderr
            sys.stdout, sys.stderr = stringio, stringio
            yield output
        finally:
            sys.stdout, sys.stderr = out, err
            output.extend(stringio.getvalue().splitlines())
            stringio.close()
    

    with capturinglines() as output:
        print "foo"
        print "bar"
    
    print output
    ['foo', 'bar']
    
    with capturinglines(output):   # append to existing list
        print "baz"
    
    print output
    ['foo', 'bar', 'baz']
    
        4
  •  1
  •   S.Lott    14 年前

    我想你也许可以建造这样的东西。

    import StringIO
    
    capturing = StringIO.StringIO()
    print( "foo bar baz", file= capturing )
    

    现在'foo bar baz\n'== capturing.getvalue()

    print 使用 file=

        5
  •  1
  •   DevPlayer    12 年前

    如何创建一个类似字符串的类?

    str公司 无论出于什么原因:

    class StrBuiltin(object):
        def __init__(self, astr=''):
            self._str = astr
    
        def __enter__(self):
            return self
    
        def __exit__(self, ext_typ, exc_value, traceback):
            pass # do stuff
    
        def __str__(self):
            return self._str
    
        def __repr__(self):
            return repr(self._str)
    
        def __eq__(self, lvalue):
            return lvalue == self._str
    
        def str(self):
            '''pretend to "convert to a str"'''
            return self._str
    
    astr = StrBuiltin('Eggs&spam')
    
    if isinstance( astr.str(), str):
        print 'Is like a str.'
    else:
        print 'Is not like a str.'
    

    我知道你不想做str(MyClass),但MyClass.str()对我来说意味着,这个类应该将自己作为str公开给那些希望str作为对象一部分的函数。而不是“who know's what will be return by str(SomeObject)”的意外结果。