开发者

where is the instancemethod decorator?

开发者 https://www.devze.com 2023-02-24 04:51 出处:网络
In my code I have a method that returns an instance of a class, like this: class MyClass: def fun( self, *args ): # the method

In my code I have a method that returns an instance of a class, like this:

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

To keep things organized I am considering to place Props inside MyClass. I would then like to bypass fun and directly make the class an instance method of MyClass, like this:

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

Note the comment - the instancemethod decorator does not exist.

Is there a way to do this, i.e. to turn a callable object into an instance method? If I change @instancemethod to @classmethod the construction works, except then of course parent is the class, not the instance. I am surprised that I cannot find anything about what seems to be the opposite operation.

Curious to have this cleared up!

Edit:

It seems that my quest开发者_运维技巧ion was not clear. What I have is a member function, fun, that returns not a single value or tuple but an object full of data. This data is generated based on the contents of the MyClass object and function arguments. My initial code does exactly what I want. The second code is how I would prefer to write it.

Moreover I noticed that the decorator I am looking for is simply the following:

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

It is, of course, identical to the 'fun' method that I aimed to bypass. Note also that the trivial 'return cls' is not identical, even though it might seem like that at first sight.

With this decorator, my second class definition is valid and produces the desired result, namely, a.fun() returns an object that is (potentially) initialized based on the data in 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)

This still leaves me with the question if the instancemethod defined here is not available as a python builtin, because it seems an omission next to classmethod and staticmethod. But, if not, I suppose I can live with this construction.


I'm not sure exactly what you're trying to do, but I suspect you want to read up on descriptors.

Basically, a descriptor is an attribute of a class that is itself a class that defines __get__ and __set__ methods. In your case, you could move the code from Props.__init__ to Props.__set__, set Props as the fun attribute of the class, and all should work as you want.


I think you're overcomplicating things for no reason; perhaps you're accustomed to other languages and want to bring over your habits from there.

IIUC, you intend to do something like:

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)


You don't need an instancemethod decorator, this could should work:

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

You could also change your first example to

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
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号