Re: Why require __init__ to return None?

Donald Beaudry (don@vicorp.com)
Tue, 31 May 94 11:09:08 EDT

>>>>> On Sat, 28 May 1994 00:43:18 +0200, Guido.van.Rossum@cwi.nl said:

> I was thinking of the same thing. I would like to solve it in another
> way, by introducing the operator __call__ for instances.

g> This is indeed a useful extension. I might add it sooner or later
g> -- sooner if someone contributes a working patch!

The patch I made allows any built-in type to overload the call
operator. I have not patched the instance object to make use of this
but I am sure it would be trivial to do. Since there is a macro for
creating a function that can be used to overload any binary operator,
all you need to do is add the line:

BINARY(instance_call, "__call__")

at a suitable place in Object/instance.c, then add an entry for
'instance_call' to the static instantiation of the instance type
object.

So, the patch is as follows:

The _typeobject structure has a new field called tp_call. For any
type that you would like to call, simply add a pointer to a
'binaryfunc' that does the right thing. Writing one of these for the
instance object is not even necessary (as I mentioned above).

(As I hinted in a previous message, I would like to see a new method
suite added that would hold all of the current 'standard methods'.)

In Include/object.h replace the _typeobject structure with
following:

typedef struct _typeobject {
OB_VARHEAD
char *tp_name; /* For printing */
unsigned int tp_basicsize, tp_itemsize; /* For allocation */

/* Methods to implement standard operations */

destructor tp_dealloc;
printfunc tp_print;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
cmpfunc tp_compare;
reprfunc tp_repr;

/* Method suites for standard classes */

number_methods *tp_as_number;
sequence_methods *tp_as_sequence;
mapping_methods *tp_as_mapping;

/* More standard operations (at end for binary compatibility) */

hashfunc tp_hash;
binaryfunc tp_call;
#ifdef COUNT_ALLOCS
/* these must be last */
int tp_alloc;
int tp_free;
int tp_maxalloc;
struct _typeobject *tp_next;
#endif
} typeobject;

in Python/ceval.c replace call_object() with the following:

object *
call_object(func, arg)
object *func;
object *arg;
{
binaryfunc call;

if (call = func->ob_type->tp_call) {
int size = gettuplesize(arg);
if (arg) {
size = gettuplesize(arg);
if (size == 1)
arg = gettupleitem(arg, 0);
else if (size == 0)
arg = NULL;
}
return (*call)(func, arg);
}

if (is_instancemethodobject(func) || is_funcobject(func))
return call_function(func, arg);
else
return call_builtin(func, arg);
}

Now, arguably, I should have patched up all of the callable types to
make use of this new feature, rather than just add a new special case
to the call_object routine, but...

--Don