【问题标题】:where is the instancemethod decorator?instancemethod 装饰器在哪里?
【发布时间】:2011-04-12 08:47:51
【问题描述】:

在我的代码中,我有一个返回类实例的方法,如下所示:

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 中。然后我想绕过fun,直接让类成为MyClass的实例方法,像这样:

class MyClass:
  @instancemethod # does not exist!
  class fun:
    def __init__( self, parent, *args ):
      self.parent = parent
      self.args = args

注意注释 - instancemethod 装饰器不存在。

有没有办法做到这一点,即将可调用对象转换为实例方法?如果我将@instancemethod 更改为@classmethod,则构造工作,当然,父类是类,而不是实例。我很惊讶我找不到任何关于似乎相反的操作的信息。

很想解决这个问题!

编辑:

看来我的问题并不清楚。我所拥有的是一个成员函数 fun,它返回的不是单个值或元组,而是一个充满数据的对象。此数据是根据 MyClass 对象和函数参数的内容生成的。我的初始代码完全符合我的要求。第二个代码是我喜欢的写法。

此外,我注意到我正在寻找的装饰器只是以下内容:

def instancemethod( cls ):
  def f( *args ):
    return cls( *args )
  return f

当然,这与我打算绕过的“有趣”方法相同。另请注意,微不足道的“返回 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 旁边的遗漏。但是,如果不是,我想我可以接受这种结构。

【问题讨论】:

  • 可调用对象必须实现__call__方法
  • 第一个代码 sn-p 看起来更有条理。 jast move Proops fun 函数体中的类定义

标签: python decorator instance-method


【解决方案1】:

我不确定你到底想做什么,但我怀疑你想阅读descriptors

基本上,描述符是一个类的属性,它本身就是一个定义__get____set__ 方法的类。在您的情况下,您可以将代码从Props.__init__ 移动到Props.__set__,将Props 设置为类的fun 属性,所有这些都应该按照您的意愿工作。

【讨论】:

  • 谢谢,但我认为描述符不能解决我的问题。我希望创建一个基于 MyClass 对象和参数返回对象的函数。据我所知,描述符不能处理参数,因为它们的行为类似于属性。如果我错了,请纠正我。我更新了我的问题以更好地解释我的目标,并建议了我希望找到的特定装饰器作为 python 内置。
  • @gertjan:Descriptors 方法可以接受参数。属性设置、获取、删除都可以通过它们完全自定义。
  • möter:恐怕我无法理解如何使用描述符获得所需的行为,但我很好奇。您能否在我更新的帖子中发布您建议的代码以重现该示例?
【解决方案2】:

我认为你无缘无故地把事情复杂化了;也许您已经习惯了其他语言,并希望从那里继承您的习惯。

IIUC,你打算这样做:

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)

【讨论】:

    【解决方案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
    

    【讨论】:

    • 谢谢,但恐怕不行,我特别需要 f.parent 是 m,而不是 None。我想调用 m.fun(1,2,3),并让 python 作为第一个参数传递 m,就像在我的示例中一样。该示例被精简,实际上我会使用父级来计算真实属性。
    猜你喜欢
    • 2019-05-07
    • 2021-04-11
    • 2018-10-17
    • 2018-01-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2014-05-12
    • 2012-09-15
    相关资源
    最近更新 更多