user277465
user277465

Reputation:

replacing the "new" module

I have code which contains the following two lines in it:-

instanceMethod = new.instancemethod(testFunc, None, TestCase)
setattr(TestCase, testName, instanceMethod)

How could it be re-written without using the "new" module? Im sure new style classes provide some kind of workaround for this, but I am not sure how.

Upvotes: 6

Views: 3734

Answers (4)

Oliver
Oliver

Reputation: 29611

You can replace "new.instancemethod" by "types.MethodType":

from types import MethodType as instancemethod

class Foo: 
    def __init__(self):
        print 'I am ', id(self)

def bar(self): 
    print 'hi', id(self)

foo = Foo()  # prints 'I am <instance id>'
mm = instancemethod(bar, foo) # automatically uses foo.__class__
mm()         # prints 'I have been bound to <same instance id>'

foo.mm       # traceback because no 'field' created in foo to hold ref to mm
foo.mm = mm  # create ref to bound method in foo
foo.mm()     # prints 'I have been bound to <same instance id>'

Upvotes: 5

pyfunc
pyfunc

Reputation: 66739

There is a discussion that suggests that in python 3, this is not required. The same works in Python 2.6

See:

>>> class C: pass
... 
>>> c=C()
>>> def f(self): pass
... 
>>> c.f = f.__get__(c, C)
>>> c.f
<bound method C.f of <__main__.C instance at 0x10042efc8>>
>>> c.f
<unbound method C.f>
>>> 

Reiterating the question for every one's benefit, including mine.

Is there a replacement in Python3 for new.instancemethod? That is, given an arbitrary instance (not its class) how can I add a new appropriately defined function as a method to it?

So following should suffice:

TestCase.testFunc = testFunc.__get__(None, TestCase)

Upvotes: 10

geertjanvdk
geertjanvdk

Reputation: 3520

To confirm that it's not needed to use new.instancemthod() at all since Python v2.4, here's an example how to replace an instance method. It's also not needed to use descriptors (even though it works).

class Ham(object):
    def spam(self):
        pass

h = Ham()
def fake_spam():
    h._spam = True
h.spam = fake_spam
h.spam()

# h._spam should be True now.

Handy for unit testing.

Upvotes: 0

Lennart Regebro
Lennart Regebro

Reputation: 172377

This will do the same:

>>> Testcase.testName = testFunc

Yeah, it's really that simple.

Your line

>>> instanceMethod = new.instancemethod(testFunc, None, TestCase)

Is in practice (although not in theory) a noop. :) You could just as well do

>>> instanceMethod = testFunc

In fact, in Python 3 I'm pretty sure it would be the same in theory as well, but the new module is gone so I can't test it in practice.

Upvotes: 1

Related Questions