Python 用简单函数替换类方法

Python 用简单函数替换类方法,python,python-3.x,Python,Python 3.x,作为这里的一个例子,我想创建一个函数来临时将stdout指向一个日志文件 棘手的是,代码必须保留文件处理程序和std sav,以便在重定向后恢复。我在类类型中编写了它,以保留这两个变量 以下是完整代码: class STDOUT2file: def __init__(self,prefix='report@'): now=dt.date.today() repname=repnameprefix=prefix+now.strftime("%Y%m%d")

作为这里的一个例子,我想创建一个函数来临时将stdout指向一个日志文件

棘手的是,代码必须保留文件处理程序和std sav,以便在重定向后恢复。我在类类型中编写了它,以保留这两个变量

以下是完整代码:

class STDOUT2file:
    def __init__(self,prefix='report@'):

        now=dt.date.today()
        repname=repnameprefix=prefix+now.strftime("%Y%m%d")+'.txt'
        count=0
        while os.path.isfile(repname):
            count+=1
            repname=repnameprefix+(".%02d" %(count))
        self.sav=sys.stdout
        f=open(repname,'w')
        sys.stdout=f
        self.fname=repname
        self.fhr=f


    def off(self,msg=False):

        sys.stdout=self.sav
        self.fhr.close()
        if msg: 
            print('output to:'+self.fname)
        return
以下是应用它的代码:

outbuf=STDOUT2file()

#codes to print out to stdout

outbuf.off(msg=True)
我想让它更清晰,阅读有关“closure”的内容,但它在第一次调用时返回一个函数,类似于类的assignment类型

我希望它像:

stdout2文件('on')

STDout2file('off',msg=True)


注意:重定向到stdout是我刚才遇到的一个例子。。我想知道的是,除了类类型之外,还有什么其他方法可以实现像开/关类型这样的简单功能,其中包括存储/检索状态变量,这些变量最好让外部看不见。

尝试使用上下文管理器。此成语非常常见,因此包含在(此处稍作修改):

或者,如果愿意,使用基于类的版本,包括
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
\uuuuuuuuuuuuuuuuuuuu

class redirect_stdout:
    """Context manager for temporarily redirecting stdout to another file

    docstring truncated
    """

    def __init__(self, new_target):
        self.new_target = new_target

    def __enter__(self):
        self.old_target = sys.stdout
        sys.stdout = self.new_target
        return self.new_target

    def __exit__(self, exctype, excinst, exctb):
        sys.stdout = self.old_target
Raymond Hettinger实际上,它将作为一个组件包含在python 3.4中

基本用法:

with open('somelogfile','a') as f:
    with stdout_redirected(f):
        print(something)

尝试改用上下文管理器。此成语非常常见,因此包含在(此处稍作修改):

或者,如果愿意,使用基于类的版本,包括
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
\uuuuuuuuuuuuuuuuuuuu

class redirect_stdout:
    """Context manager for temporarily redirecting stdout to another file

    docstring truncated
    """

    def __init__(self, new_target):
        self.new_target = new_target

    def __enter__(self):
        self.old_target = sys.stdout
        sys.stdout = self.new_target
        return self.new_target

    def __exit__(self, exctype, excinst, exctb):
        sys.stdout = self.old_target
Raymond Hettinger实际上,它将作为一个组件包含在python 3.4中

基本用法:

with open('somelogfile','a') as f:
    with stdout_redirected(f):
        print(something)

可以,您可以在函数中保存状态信息。只要命名变量functionname.something,它就会被保存。例如:

def stdout2file(status, prefix='pre', msg=False):
    import datetime as dt
    import os
    import sys
    if not hasattr(stdout2file, 'sav'):
        stdout2file.sav = None
    if status == 'on':
        if stdout2file.sav:
            print('You have already triggered this once  Ignoring this request.')
        else:
            now = dt.date.today()
            repname = repnameprefix = prefix + now.strftime("%Y%m%d") + '.txt'
            count = 0
            while os.path.isfile(repname):
                count += 1
                repname = repnameprefix + (".%02d" %(count))
            stdout2file.sav = sys.stdout
            f = open(repname,'w')
            sys.stdout = f
            stdout2file.fhr = f
    elif status == 'off':
        if not stdout2file.sav:
            print('Redirect is "off" already.  Ignoring this request')
        else:
            sys.stdout = stdout2file.sav
            stdout2file.fhr.close()
            if msg:
                print('output to:' + stdout2file.fhr.name)
            stdout2file.sav = None
    else:
        print('Unrecognized request')
还可以在可变关键字参数中保留状态信息,如:

def stdout_toggle(prefix='pre', msg=False, _s=[None, None]):
    import datetime as dt
    import os
    import sys
    if _s[0] is None:
        now = dt.date.today()
        repname = repnameprefix = prefix + now.strftime("%Y%m%d") + '.txt'
        count = 0
        while os.path.isfile(repname):
            count += 1
            repname = repnameprefix + (".%02d" %(count))
        f = open(repname,'w')
        _s[:] = [sys.stdout, f]
        sys.stdout = f
    else:
        sys.stdout = _s[0]
        _s[1].close()
        if msg:
            print('output to:' + _s[1].name)
        _s[:] = [None, None]
用户可以不带任何参数调用上述函数,它将在重定向的on和off之间切换。该函数通过关键字参数
\u s
记住当前状态,该参数是一个可变列表


尽管有人认为在函数调用之间保留可改变的关键字参数是语言缺陷的事实,但它与Python哲学是一致的。这是因为关键字参数的默认值是在首次定义函数时指定的,即执行

def
语句时,而不是在调用函数时指定的。因此,
\u s=[None,None]
在定义时分配一次,之后可以自由更改。

是的,您可以在函数中保存状态信息。只要命名变量functionname.something,它就会被保存。例如:

def stdout2file(status, prefix='pre', msg=False):
    import datetime as dt
    import os
    import sys
    if not hasattr(stdout2file, 'sav'):
        stdout2file.sav = None
    if status == 'on':
        if stdout2file.sav:
            print('You have already triggered this once  Ignoring this request.')
        else:
            now = dt.date.today()
            repname = repnameprefix = prefix + now.strftime("%Y%m%d") + '.txt'
            count = 0
            while os.path.isfile(repname):
                count += 1
                repname = repnameprefix + (".%02d" %(count))
            stdout2file.sav = sys.stdout
            f = open(repname,'w')
            sys.stdout = f
            stdout2file.fhr = f
    elif status == 'off':
        if not stdout2file.sav:
            print('Redirect is "off" already.  Ignoring this request')
        else:
            sys.stdout = stdout2file.sav
            stdout2file.fhr.close()
            if msg:
                print('output to:' + stdout2file.fhr.name)
            stdout2file.sav = None
    else:
        print('Unrecognized request')
还可以在可变关键字参数中保留状态信息,如:

def stdout_toggle(prefix='pre', msg=False, _s=[None, None]):
    import datetime as dt
    import os
    import sys
    if _s[0] is None:
        now = dt.date.today()
        repname = repnameprefix = prefix + now.strftime("%Y%m%d") + '.txt'
        count = 0
        while os.path.isfile(repname):
            count += 1
            repname = repnameprefix + (".%02d" %(count))
        f = open(repname,'w')
        _s[:] = [sys.stdout, f]
        sys.stdout = f
    else:
        sys.stdout = _s[0]
        _s[1].close()
        if msg:
            print('output to:' + _s[1].name)
        _s[:] = [None, None]
用户可以不带任何参数调用上述函数,它将在重定向的on和off之间切换。该函数通过关键字参数
\u s
记住当前状态,该参数是一个可变列表


尽管有人认为在函数调用之间保留可改变的关键字参数是语言缺陷的事实,但它与Python哲学是一致的。这是因为关键字参数的默认值是在首次定义函数时指定的,即执行

def
语句时,而不是在调用函数时指定的。因此,
\u s=[None,None]
在定义时分配一次,之后可以自由更改。

tks。但是重定向到stdout只是一个例子。。我想问的是,如果我想做一些功能,包括存储某些状态变量,这些变量将在以后检索,并且我想封装(或使其不可见)这些变量,我可以做除类类型之外的其他操作吗?对于一些简单的函数,如开/关类型,这是一个overkill.tks。但是重定向到stdout只是一个例子。。我想问的是,如果我想做一些功能,包括存储某些状态变量,这些变量将在以后检索,并且我想封装(或使其不可见)这些变量,我可以做除类类型之外的其他操作吗?对于一些简单的函数,如开/关类型,这是一种过分的操作。您的代码可以工作!顺便问一下,如何避免重定向被触发两次?检查stdout2file.sav是否为none不起作用,因为它是“定义之前的引用”,tkyou@时间是爱的。我添加了检查,这样,如果一行中有两个“开”或两个“关”请求,则只处理第一个请求。如果不先打开,If也会拒绝关闭。虽然转换工作正常,但它看起来比我预期的代码行多,比使用类类型的代码行多。。。嗯…你在说什么?它的行数应该与类版本的行数相同,因为唯一的更改是
self.save
stdout2file.sav
@timeislove。有一些多余的行,我删除了它们。例如,没有必要保留
stdout2file.fname
,因为相同的信息在
stdout2file.fhr.name
中。还要注意,我在函数中包含了三个
import
语句。该类需要相同的导入,但它们没有显示在类定义中。您的代码可以正常工作!顺便问一下,如何避免重定向被触发两次?检查stdout2file.sav是否为none不起作用,因为它是“定义之前的引用”,tkyou@时间是爱的。我添加了检查,这样,如果一行中有两个“开”或两个“关”请求,则只处理第一个请求。如果不先打开,If也会拒绝关闭。虽然转换工作正常,但它看起来比我预期的代码行多,比使用类类型的代码行多。。。嗯…你在说什么?它的行数应该与类版本的行数相同,因为唯一的更改是
self.save
stdout2file.sav
@timeislove。有一些多余的行,我删除了它们。例如,不需要保留
stdout2file.fname
ar