如何制作一个像字符串一样的类?

kin*_*all 3 python string with-statement

我有一个上下文管理器,它将输出捕获到一个字符串中,用于在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"
Run Code Online (Sandbox Code Playgroud)

当然,我不能只返回一个字符串,因为字符串是不可变的,因此用户从with语句中返回的字符串在他们的代码块运行后无法更改。但是,事后必须将结果对象显式转换为字符串是一件很麻烦的事str(我还尝试将对象作为一种语法糖来调用)。

那么是否有可能使结果实例像一个字符串一样运行,因为它实际上在命名时返回一个字符串?我尝试实现__get__,但这似乎只适用于属性。或者我想要做的事情真的不可能?

Dev*_*yer 5

如何制作一个像字符串一样的类? 子类str

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:\\'
Run Code Online (Sandbox Code Playgroud)

输出:

1 D:\Projects\Python\
2 C:\
3 D:\Projects\Python\
4 True
Run Code Online (Sandbox Code Playgroud)