我有两个类(我们称之为Working和ReturnStatement),我不能修改它们,但是我想用日志扩展这两个类。诀窍是,Working的方法返回一个ReturnStatement对象,所以新的mutantWorking对象也返回ReturnStatement,除非我可以将其强制转换为mutantreturnStatement。用代码说:

# these classes can't be changed
class ReturnStatement(object):
    def act(self):
        print "I'm a ReturnStatement."

class Working(object):
    def do(self):
        print "I am Working."
        return ReturnStatement()

# these classes should wrap the original ones
class MutantReturnStatement(ReturnStatement):
    def act(self):
        print "I'm wrapping ReturnStatement."
        return ReturnStatement().act()

class MutantWorking(Working):
    def do(self):
        print "I am wrapping Working."
        # !!! this is not working, I'd need that casting working !!!
        return (MutantReturnStatement) Working().do()

rs = MutantWorking().do() #I can use MutantWorking just like Working
print "--" # just to separate output
rs.act() #this must be MutantReturnState.act(), I need the overloaded method

预期结果:
我正在包装工作。
我在工作。
——
我正在包装退货声明。
我是一个返回声明。
有可能解决这个问题吗?我也很好奇这个问题是否也可以用PHP来解决。除非我得到一个有效的解决方案,否则我不能接受这个答案,所以请写下有效的代码来被接受。

最佳答案

其他答案已经解释过了,没有演员阵容。您可以使用decorator创建子类或使用额外的功能创建修改后的新类型。
这是一个完整的例子(归功于How to make a chain of function decorators?)。您不需要修改原始类。在我的示例中,原始类称为Working。

# decorator for logging
def logging(func):
    def wrapper(*args, **kwargs):
        print func.__name__, args, kwargs
        res = func(*args, **kwargs)
        return res
    return wrapper

# this is some example class you do not want to/can not modify
class Working:
    def Do(c):
        print("I am working")
    def pr(c,printit):   # other example method
        print(printit)
    def bla(c):          # other example method
        c.pr("saybla")

# this is how to make a new class with some methods logged:
class MutantWorking(Working):
    pr=logging(Working.pr)
    bla=logging(Working.bla)
    Do=logging(Working.Do)

h=MutantWorking()
h.bla()
h.pr("Working")
h.Do()

这将打印
h.bla()
bla (<__main__.MutantWorking instance at 0xb776b78c>,) {}
pr (<__main__.MutantWorking instance at 0xb776b78c>, 'saybla') {}
saybla

pr (<__main__.MutantWorking instance at 0xb776b78c>, 'Working') {}
Working

Do (<__main__.MutantWorking instance at 0xb776b78c>,) {}
I am working

另外,我想知道为什么你不能修改一个类。你试过了吗?因为,作为创建子类的替代方法,如果您感到有活力,几乎可以在适当的位置修改一个旧类:
Working.Do=logging(Working.Do)
ReturnStatement.Act=logging(ReturnStatement.Act)

更新:将日志记录应用于类的所有方法
正如你现在特别要求的。您可以循环所有成员,并将日志记录应用于所有成员。但是您需要为要修改的成员类型定义一个规则。下面的示例排除了名称中有_uuu的任何方法。
import types
def hasmethod(obj, name):
    return hasattr(obj, name) and type(getattr(obj, name)) == types.MethodType

def loggify(theclass):
  for x in filter(lambda x:"__" not in x, dir(theclass)):
     if hasmethod(theclass,x):
        print(x)
        setattr(theclass,x,logging(getattr(theclass,x)))
  return theclass

有了这些,您需要做的就是创建一个类的新的日志版本:
@loggify
class loggedWorker(Working): pass

或就地修改现有类:
loggify(Working)

10-07 12:30