Python stealer method

How can I β€œsteal” or copy a method from one class to another class?

Code example:

class A(object): def foo(self): print "blah" class B(object): foo = A.foo B().foo() 

Expected Result:

 "blah" 

Instead

TypeError: unbound method foo () should be called with instance A as the first argument (nothing happens instead)

+6
source share
3 answers

Use __func__ :

 >>> A.foo <unbound method A.foo> >>> A.foo.__func__ <function foo at 0x00BC5F70> >>> class B(object): ... foo = A.foo.__func__ ... >>> B().foo() "blah" 

Quote docs :

An instance method object combines a class, an instance of a class, and any called object (usually a user-defined function).

Special read-only attributes: __self__ is an object of an instance of a class, __func__ is a function object; __doc__ is the documentation of the methods (same as __func __.__ doc__); __name__ is the name of the method (same as __func __.__ name__); __module__ is the name of the module in which the method was defined, or None if it is not available.

+6
source

The problem is that this is a related method that you are trying to steal, however your example does not include a function that uses the state of the instance ( self ). Therefore, you have two instant options:

  • Make A.foo definition a static method ( @staticmethod decorator)
  • Decorate or wrap the function to pass an unused argument. For instance. using functools .

Eg.

 import functools stolen = functools.partial(A.foo, None) 

This works because your method does not use instance state and does not require subclassing.

To A.foo bit, a linked instance method (e.g. A.foo ) expects a bound instance argument ( self , where self is an instance of A ). Under normal use, this first argument is passed automatically:

 a = A() 

Now:

 a.foo() A.foo(a) 

... Both are equivalent. In the first case, the syntax of instance.bound_method() infers InstanceClass.bound_method(instance) from the lexical point of view ( instance resolves to self ). This is why calling A.foo() will A.foo() because it expects an instance of A

What the above solution does is to turn the function into one that passes None as an instance, since the instance is never used anyway (there is no state logic). When using staticmethod, it removes the 1st implied expected argument of the associated instance of self .

+2
source

Here you can use class inheritance . Inheritance allows you to create an object based on another object, inheriting all its functions and attributes.

In this case, it looks like this:

 class A(object): def foo(self): print "blah" class B(A): # You can add new methods or attributes here, # or even overwrite those inherited from A if you # really want to, though you have to be careful with that. pass 

After this announcement

 >>> B().foo() "blah" 

This works because:

  • You created class A and created the foo method for it.
  • You created a class B that inherits from A , which means that when A "gave birth to it," B born with everything that A .
    • In our case, B is an exact copy of A , since we did not do anything with it. However, we could make changes or add other methods.

Example:

 class A(object): def foo(self): print "blah" class B(A): def newfoo(self): print "class A can't do this!" 

In this case, we will see:

 >>> A().foo() blah >>> B().foo() blah >>> A().newfoo() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'A' object has no attribute 'newfoo' >>> B().newfoo() class A can't do this! 

In particular, the reason your code above did not work is because when you tried to install B.foo , you wrote

 class B(object): foo = A.foo 

instead

 class B(object): foo = A().foo 

When you wrote A.foo without () , you requested a method directly from type A that would not work in Python. If you need to execute foo = A().foo , then you must create an instance of object A , then get a copy of your foo method and then assign it.

+1
source

All Articles