Final Edit
My problem was that I was trying to bind a partial to a class. Not sure if I should delete this question or, change its title.
Original Question
I know that the "correct" way to bind methods to a class inside its metaclass is to add it to the classdict
argument in the metaclass's __new__
method, and that in general you can bind an instance method to a class by simply assigning it to the class.
However, in my use case, I need to bind a method to a class during the metaclass's __init__
method. The problem is that the usual method of assignment does not work. The function is assigned to the class and it can be access via ClassName.function_name
or class_instance.function_name
, but it is not bound to the class, and the first argument is not set to self
.
I guess that this is due to the class not being fully initialized during the metaclass __init__
, but is there any way around this problem?
EDIT: Code Example
Given:
def fun(self):
pass
class MetaClass(type):
def __init__(cls, name, bases, dct):
pass
class Class(object):
__metaclass__ = MetaClass
I want to bind fun
to Class
inside MetaClass.__init__
, so that calling
instance = Class()
instance.fun()
will pass instance
to fun
as its first argument.
Edit The II
So, apparently the problem arose because I was trying to bind a partial. Not sure why that would cause an issue.
Will make sure later, and update/remove this question if necessary.
The __call__ method enables Python programmers to write classes where the instances behave like functions and can be called like a function. When the instance is called as a function; if this method is defined, x(arg1, arg2, ...) is a shorthand for x. __call__(arg1, arg2, ...) .
A bound method is the one which is dependent on the instance of the class as the first argument. It passes the instance as the first argument which is used to access the variables and functions.
The __new__() is a static method of the object class. It has the following signature: object.__new__(class, *args, **kwargs) Code language: Python (python) The first argument of the __new__ method is the class of the new object that you want to create.
The __bases__ property of the class contains a list of all the base classes that the given class inherits. The above output shows that the Human class has object as a base class. We can also look at the attributes and methods defined by the object class using the dir function.
There is little difference between metaclass.__new__()
and metaclass.__init__()
; they both deal with the class object.
__new__
produces the new object, __init__
then gets to alter it still. The chain of events is basically:
new_class_obj = YourMeta.__new__(YourMeta, name, bases, bodydict)
YourMeta.__init__(new_class_obj, name, bases, bodydict)
When it comes to adding functions on the new class object (through the bodydict
or directly by assignment on the class object) there is no difference at all.
If you are having problems setting functions on the class object, then you need to make sure you are setting actual function objects on that object.
If you are using bound methods for example, you need to unwrap the method and extract just the function:
new_class_obj.name = method_obj.__func__
If you are adding regular function objects on the class, then they'll be bound when accessed on the instance, no work required on your part.
Bottom line is that you need to add something that'll act a descriptor, specifically a descriptor that'll return a method object from the descriptor.__get__
method. This is what plain function objects do.
A functools.partial()
object is not such a descriptor. Easiest would be to wrap the partial in a function (a lambda
will do here):
new_class_obj.name = lambda *args, **kw: partial_obj(*args, **kw)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With