Adding a Method to an Existing Object Instance

Adding a Method to an Existing Object Instance

Asked on October 15, 2018 in Python.
Add Comment


  • 5 Answer(s)

    In Python, there’s a distinction between functions and sure strategies.

    >> def foo():
    ...     print "foo"
    ...
    class A:
    ...     def bar( self ):
    ...         print "bar"
    ...
    a = A()
    foo
    <function foo at 0x00A98D70>
    a.bar
    <bound method A.bar of <__main__.A instance at 0x00A9BC88>>
    

    Bound strategies are “bound” (how descriptive) to associate instance, which instance are going to be passed because the 1st argument whenever the tactic is termed.

    Callables that area unit attributes of a category (as critical associate instance) area unit still unbound, though, therefore you’ll modify the category definition whenever you want:

    >> def fooFighters( self ): ... print "fooFighters" ... A.fooFighters = fooFighters a2 = A() a2.fooFighters <bound method A.fooFighters of <__main__.A instance at 0x00A9BEB8>> a2.fooFighters() fooFighters

    Previously outlined instances area unit updated still (as long as they haven’t overridden the attribute themselves):

    >> a.fooFighters()
    fooFighters
    

    This time different instances of the category haven’t been affected:

    >> def barFighters( self ):
    ...        print "barFighters"
    ...
    a.barFighters = barFighters
    a.barFighters()
    Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
    TypeError: barFighters() takes exactly 1 argument (0 given)
    

    The function is not automatically bound when it’s attached directly to an instance:

    >> a.barFighters
    <function barFighters at 0x00A98EF0>
    

    To bind it, we can use the MethodType function in the types module:

    >> import types a.barFighters = types.MethodType( barFighters, a ) a.barFighters <bound method ?.barFighters of <__main__.A instance at 0x00A9BC88>> a.barFighters() barFighters

    This time other instances of the class have not been affected:

    >>> a2.barFighters()
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    AttributeError: A instance has no attribute 'barFighters'
    
    Answered on October 15, 2018.
    Add Comment

    In the example below I’ve deliberately removed come worth from patch_me() perform. i feel that giving come worth might create one believe that patch returns a brand new object, that isn’t true – it modifies the incoming one. in all probability this may facilitate a a lot of disciplined use of monkeypatching.

    import types
    class A(object):#but seems to work for old style objects too
    pass
    def patch_me(target):
        def method(target,x):
            print "x=",x
            print "called from", target
        target.method = types.MethodType(method,target)
        #add more if needed
    a = A()
    print a
    #out: <__main__.A object at 0x2b73ac88bfd0>
    patch_me(a) #patch instance
    a.method(5)
    #out: x= 5
    #out: called from <__main__.A object at 0x2b73ac88bfd0>
    patch_me(A)
    A.method(6) #can patch class too
    #out: x= 6
    #out: called from <class '__main__.A'>
    
    Answered on October 15, 2018.
    Add Comment

    In Python monkey fixture usually works by overwriting a category or functions signature along with your own. Below is AN example from the Zope Wiki:

    from SomeOtherProduct.SomeModule import SomeClass
    def speak(self):
        return "ook ook eee eee eee!"
    SomeClass.speak = speak
    
    Answered on October 15, 2018.
    Add Comment
    >>> class A:
    ...  def m(self):
    ...   print 'im m, invoked with: ', self
    
    >>> a = A()
    >>> a.m()
    im m, invoked with:  <__main__.A instance at 0x973ec6c>
    >>> a.m
    <bound method A.m of <__main__.A instance at 0x973ec6c>>
    >>> 
    >>> def foo(firstargument):
    ...  print 'im foo, invoked with: ', firstargument
    
    >>> foo
    <function foo at 0x978548c>
    
    
    1:
    >>> a.foo = foo.__get__(a, A) # or foo.__get__(a, type(a))
    >>> a.foo()
    im foo, invoked with:  <__main__.A instance at 0x973ec6c>
    >>> a.foo
    <bound method A.foo of <__main__.A instance at 0x973ec6c>>
    
    
    2:
    
    >>> instancemethod = type(A.m)
    >>> instancemethod
    <type 'instancemethod'>
    >>> a.foo2 = instancemethod(foo, a, type(a))
    >>> a.foo2()
    im foo, invoked with:  <__main__.A instance at 0x973ec6c>
    >>> a.foo2
    <bound method instance.foo of <__main__.A instance at 0x973ec6c>>

     

     

    Answered on January 14, 2019.
    Add Comment

    In Python, there is a difference between functions and bound methods.

    >>> def foo():
    ...     print "foo"
    ...
    >>> class A:
    ...     def bar( self ):
    ...         print "bar"
    ...
    >>> a = A()
    >>> foo
    <function foo at 0x00A98D70>
    >>> a.bar
    <bound method A.bar of <__main__.A instance at 0x00A9BC88>>
    >>>

    Bound methods have been “bound” (how descriptive) to an instance, and that instance will be passed as the first argument whenever the method is called.

    Callables that are attributes of a class (as opposed to an instance) are still unbound, though, so you can modify the class definition whenever you want:

    >>> def fooFighters( self ):
    ...     print "fooFighters"
    ...
    >>> A.fooFighters = fooFighters
    >>> a2 = A()
    >>> a2.fooFighters
    <bound method A.fooFighters of <__main__.A instance at 0x00A9BEB8>>
    >>> a2.fooFighters()
    fooFighters

    Previously defined instances are updated as well (as long as they haven’t overridden the attribute themselves):

    >>> a.fooFighters()
    fooFighters

    The problem comes when you want to attach a method to a single instance:

    >>> def barFighters( self ):
    ...     print "barFighters"
    ...
    >>> a.barFighters = barFighters
    >>> a.barFighters()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: barFighters() takes exactly 1 argument (0 given)

    The function is not automatically bound when it’s attached directly to an instance:

    >>> a.barFighters
    <function barFighters at 0x00A98EF0>

    To bind it, we can use the MethodType function in the types module:

    >>> import types
    >>> a.barFighters = types.MethodType( barFighters, a )
    >>> a.barFighters
    <bound method ?.barFighters of <__main__.A instance at 0x00A9BC88>>
    >>> a.barFighters()
    barFighters

    This time other instances of the class have not been affected:

    >>> a2.barFighters()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: A instance has no attribute 'barFighters'
    Answered on February 9, 2019.
    Add Comment


  • Your Answer

    By posting your answer, you agree to the privacy policy and terms of service.