如何在Python中投射对象 [英] How to cast object in Python

查看:152
本文介绍了如何在Python中投射对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个类(我们称之为Working和ReturnStatement),我不能修改,但是我想用日志记录扩展它们。诀窍是Working's方法返回一个ReturnStatement对象,所以新的MutantWorking对象也返回ReturnStatement,除非我可以把它转换为MutantReturnStatement。使用代码:

 #这些类不能更改
class ReturnStatement(object):
def act(self):
print我是一个ReturnStatement。

class Working(object):
def do(self):
printI'm Working。
return ReturnStatement()

#这些类应该包装原始的
class MutantReturnStatement(ReturnStatement):
def act(self):
print我包装ReturnStatement。
return ReturnStatement()。act()

class MutantWorking(Working):
def do(self):
print我正在包装工作。
#!!!这不工作,我需要铸造工作!
return(MutantReturnStatement)Working()。do()

rs = MutantWorking()do()#我可以使用MutantWorking类似Working
print - 只是为了分离输出
rs.act()#this必须是MutantReturnState.act(),我需要重载的方法

预期结果:
¥b $ b我正在包装工作。

我正在工作。

-

我包装ReturnStatement。

我是一个ReturnStatement。



是否可以解决问题?我也很好奇,如果问题可以解决在PHP,太。

解决方案

有一个工作解决方案,没有铸造作为其他答案已经解释。



下面是一个完整的例子(信用了解Python装饰器)。你不需要修改你的原始类。在我的例子中,原始类称为Working。

 #用于日志记录的装饰器
def logging(func):
def wrapper(* args,** kwargs):
print func .__ name__,args,kwargs
res = func(* args,** kwargs)
return res
返回包装器

#这是一些你不想/不能修改的示例类
class Working:
def Do(c):
print(I正在工作)
def pr(c,printit):#其他示例方法
print(printit)
def bla(c):#其他示例方法
c.pr saybla)

#这是如何使用一些方法记录一个新类:
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 __。0xb776b78c>上的MutantWorking实例),{}
pr < __ main __。在0xb776b78c的突变工作实例,'saybla'){}
saybla

pr(<__ main __。在0xb776b78c的突变工作实例,'Working'){}
工作

Do(< __ main __。在0xb776b78c>上的MutantWorking实例,{}
我正在工作

此外,我想了解为什么你不能修改类。你试过吗?因为,作为一个替代制作子类,如果你感觉动态,你可以几乎总是修改一个旧类的地方:

  Working.Do = logging(Working.Do)
ReturnStatement.Act = logging(ReturnStatement.Act)
pre>

更新:将记录应用于某个类的所有方法



现在特别要求这个。您可以循环所有成员,并将日志记录应用到所有成员。但是你需要定义一个规则来修改什么类型的成员。下面的示例排除了名称中包含__的任何方法。

 导入类型
def hasmethod(obj,name)
return hasattr(obj,name)和type(getattr(obj,name))== types.MethodType

def loggify(theclass):
for x in filter x:__不在x,dir(theclass)):
如果hasmethod(theclass,x):
print(x)
setattr(theclass,x,logging ,x)))
return theclass

类的新记录版本是:

  @loggify 
class loggedWorker(working):pass



或修改现有类别:

  loggify(Working)


I have two classes (let's call them Working and ReturnStatement) which I can't modify, but I want to extend both of them with logging. The trick is that the Working's method returns a ReturnStatement object, so the new MutantWorking object also returns ReturnStatement unless I can cast it to MutantReturnStatement. Saying with code:

# 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

The expected result:
I am wrapping Working.
I am Working.
--
I'm wrapping ReturnStatement.
I'm a ReturnStatement.

Is it possible to solve the problem? I'm also curious if the problem can be solved in PHP, too. Unless I get a working solution I can't accept the answer, so please write working code to get accepted.

解决方案

There is no casting as the other answers already explained. You can make subclasses or make modified new types with the extra functionality using decorators.

Here's a complete example (credit to Understanding Python decorators). You do not need to modify your original classes. In my example the original class is called 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()

this will print

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

In addition, I would like to understand why you can not modify a class. Did you try? Because, as an alternative to making a subclass, if you feel dynamic you can almost always modify an old class in place:

Working.Do=logging(Working.Do)
ReturnStatement.Act=logging(ReturnStatement.Act)

Update: Apply logging to all methods of a class

As you now specifically asked for this. You can loop over all members and apply logging to them all. But you need to define a rule for what kind of members to modify. The example below excludes any method with __ in its name .

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

With this all you have to do to make a new logged version of a class is:

@loggify
class loggedWorker(Working): pass

Or modify an existing class in place:

loggify(Working)

这篇关于如何在Python中投射对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆