实例方法装饰器在哪里?
在我的代码中,有一个方法会返回一个类的实例,像这样:
class MyClass:
def fun( self, *args ): # the method
return Props( self, *args )
class Props: # the returned object
def __init__( self, parent, *args ):
self.parent = parent
self.args = args
为了保持代码的整洁,我在考虑把Props放进MyClass里。然后我想直接把这个类变成MyClass的一个实例方法,像这样:
class MyClass:
@instancemethod # does not exist!
class fun:
def __init__( self, parent, *args ):
self.parent = parent
self.args = args
注意注释 - instancemethod这个装饰器是不存在的。
有没有办法做到这一点,也就是把一个可调用的对象变成实例方法?如果我把@instancemethod改成@classmethod,代码就能运行了,但那样的话,parent就是类,而不是实例。我很惊讶找不到关于这个看起来相反的操作的任何信息。
我很想搞清楚这个问题!
编辑:
看来我的问题不太清楚。我有一个成员函数fun,它返回的不是单个值或元组,而是一个充满数据的对象。这些数据是根据MyClass对象的内容和函数参数生成的。我的初始代码正好实现了我想要的效果。第二段代码是我更希望的写法。
而且我注意到我在找的装饰器其实就是下面这个:
def instancemethod( cls ):
def f( *args ):
return cls( *args )
return f
当然,它和我想要绕过的'fun'方法是一样的。还要注意,简单的'return cls'并不相同,尽管乍一看可能会让人觉得是一样的。
有了这个装饰器,我的第二个类定义是有效的,并且能产生我想要的结果,也就是说,a.fun()返回的对象是(可能)根据a中的数据初始化的:
a = MyClass()
p = a.fun(1,2,3)
print a # <__main__.MyClass instance at 0xb775b84c>
print p.parent # <__main__.MyClass instance at 0xb775b84c>
print p.args # (1, 2, 3)
这让我仍然有个疑问,就是这里定义的instancemethod是不是Python内置的,因为它似乎在classmethod和staticmethod旁边被遗漏了。不过,如果没有的话,我想我可以接受这种写法。
3 个回答
你不需要一个实例方法的装饰器,这段代码应该可以正常工作:
class MyClass:
class fun:
def __init__( self, parent, *args ):
self.parent = parent
self.args = args
m = MyClass()
f = m.fun(None, 1, 2, 3)
print f.args
你也可以把你的第一个例子改成
class Props:
def __init__( self, parent, *args ):
self.parent = parent
self.args = args
class MyClass:
fun = Props
m = MyClass()
f = m.fun(None, 1, 2, 3)
print f.args
我觉得你把事情搞得太复杂了,其实没必要;可能是你习惯了其他编程语言,想把那里的习惯带过来。
如果我理解得没错的话,你想做的事情大概是这样的:
class SomeClass:
# typical stuff
def __init__(self, other, arg1, arg2, arg3, arg4):
self.parent= other
# blah blah
class SomeOtherClass:
# initialize in __init__, setup stuff
def __init__(self, initarg1, initarg2):
self.initarg1= initarg1
self.initarg2= initarg2
def fun(self, arg3, arg4):
# return an instance of SomeClass based on
# initargs and arguments
return SomeClass(self, self.initarg1, self.initarg2, arg3, arg4)
我不太确定你具体想做什么,但我猜你可能想了解一下描述符。
简单来说,描述符是一个类的属性,而这个属性本身也是一个类,它定义了__get__
和__set__
这两个方法。在你的情况下,你可以把Props.__init__
里的代码移动到Props.__set__
里,把Props
设置为这个类的fun
属性,这样一切就应该能按你想要的方式工作了。