Yet another version (by me) of __getattr__ etc.
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 9601181..8b7e4da 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -29,6 +29,10 @@
 #include "structmember.h"
 #include "ceval.h"
 
+/* Forward */
+static object *class_lookup PROTO((classobject *, char *, classobject **));
+static object *instance_getattr1 PROTO((instanceobject *, char *));
+
 object *
 newclassobject(bases, dict, name)
 	object *bases; /* NULL or tuple of classobjects! */
@@ -37,7 +41,7 @@
 {
 	int pos;
 	object *key, *value;
-	classobject *op;
+	classobject *op, *dummy;
 	if (bases == NULL) {
 		bases = newtupleobject(0);
 		if (bases == NULL)
@@ -55,6 +59,12 @@
 	op->cl_dict = dict;
 	XINCREF(name);
 	op->cl_name = name;
+	op->cl_getattr = class_lookup(op, "__getattr__", &dummy);
+	op->cl_setattr = class_lookup(op, "__setattr__", &dummy);
+	op->cl_delattr = class_lookup(op, "__delattr__", &dummy);
+	XINCREF(op->cl_getattr);
+	XINCREF(op->cl_setattr);
+	XINCREF(op->cl_delattr);
 	pos = 0;
 	while (mappinggetnext(dict, &pos, &key, &value)) {
 		if (is_accessobject(value))
@@ -223,8 +233,6 @@
 
 /* Instance objects */
 
-static object *instance_getattr PROTO((instanceobject *, char *));
-
 static int
 addaccess(class, inst)
 	classobject *class;
@@ -285,7 +293,7 @@
 		DECREF(inst);
 		return NULL;
 	}
-	init = instance_getattr(inst, "__init__");
+	init = instance_getattr1(inst, "__init__");
 	if (init == NULL) {
 		err_clear();
 		if (arg != NULL && !(is_tupleobject(arg) &&
@@ -328,7 +336,7 @@
 	   revive the object and save the current exception, if any. */
 	INCREF(inst);
 	err_get(&error_type, &error_value);
-	if ((del = instance_getattr(inst, "__del__")) != NULL) {
+	if ((del = instance_getattr1(inst, "__del__")) != NULL) {
 		object *args = newtupleobject(0);
 		object *res = args;
 		if (res != NULL)
@@ -348,76 +356,6 @@
 	free((ANY *)inst);
 }
 
-static object *instance_getattr1();
-static int instance_setattr1();
-
-static object *
-instance_getslot_meth(self, args)
-	instanceobject *self;
-	object *args;
-{
-	object *v;
-	char *name;
-	if (!getargs(args, "s", &name))
-		return NULL;
-	return instance_getattr1(self, name);
-}
-
-static object *
-instance_hasslot_meth(self, args)
-	instanceobject *self;
-	object *args;
-{
-	object *v;
-	char *name;
-	if (!getargs(args, "s", &name))
-		return NULL;
-	v = instance_getattr1(self, name);
-	if (v == NULL) {
-		err_clear();
-		return newintobject(0L);
-	}
-	DECREF(v);
-	return newintobject(1L);
-}
-
-static object *
-instance_setslot_meth(self, args)
-	instanceobject *self;
-	object *args;
-{
-	char*name;
-	object*value;
-	value = NULL;
-	if (!getargs(args, "s", &name)) {
-		err_clear();
-		if (!getargs(args, "(sO)", &name, &value))
-			return NULL;
-	}
-	if(instance_setattr1(self, name, value)<0) {
-		return NULL;
-	}
-	INCREF(None);
-	return None;
-}
-
-static object *
-instance_delslot_meth(self, args)
-	instanceobject *self;
-	object *args;
-{
-	char*name;
-	if (!getargs(args, "s", &name)) {
-			return NULL;
-	}
-	if(instance_setattr1(self, name, 0)<0) {
-		return NULL;
-	}
-	INCREF(None);
-	return None;
-}
-
-
 static object *
 instance_getattr1(inst, name)
 	register instanceobject *inst;
@@ -479,59 +417,23 @@
 	register char *name;
 {
 	register object *func, *res;
-	if (name[0] == '_' && name[1] == '_') {
-		/* Let's not compare the first "__": */
-		/* use &name[2] :-) */
-		if (strcmp(&name[2], "setslot__") == 0) {
-			return newmethodobject(name, 
-				(method)instance_setslot_meth,
-				(object*)inst,
-				0);
+	res = instance_getattr1(inst, name);
+	if (res == NULL && (func = inst->in_class->cl_getattr) != NULL) {
+		object *args;
+#if 0
+		if (name[0] == '_' && name[1] == '_') {
+			int n = strlen(name);
+			if (name[n-1] == '_' && name[n-2] == '_') {
+				/* Don't mess with system attributes */
+				return NULL;
+			}
 		}
-		if (strcmp(&name[2], "getslot__") == 0) {
-			return newmethodobject(name, 
-				(method)instance_getslot_meth,
-				(object*)inst,
-				0);
-		}
-		if (strcmp(&name[2], "hasslot__") == 0) {
-			return newmethodobject(name, 
-				(method)instance_hasslot_meth,
-				(object*)inst,
-				0);
-		}
-		if (strcmp(&name[2], "delslot__") == 0) {
-			return newmethodobject(name, 
-				(method)instance_delslot_meth,
-				(object*)inst,
-				0);
-		}
-		/* The following methods should not be forwarded! */
-		if (   strcmp(&name[2], "init__") == 0
-		    || strcmp(&name[2], "del__") == 0) {
-			return instance_getattr1(inst,name);
-		}
-	}
-	res=instance_getattr1(inst,name);
-	if (res == NULL) {
-		/* Self doesn't have this attribute, */
-		/* so let's try to call self.__getattr__(name) */
-		object* func;
-		object *arg;
-		/* Well, lets get a funcobject for __getattr__ ...*/
-		func = instance_getattr1(inst,"__getattr__");
-		if (func == NULL) {
-			/* OOPS, we don't have a  __getattr__. */
-			/* Set the error ... */
-			err_clear();
-			err_setstr(AttributeError, name);
+#endif
+		args = mkvalue("(Os)", inst, name);
+		if (args == NULL)
 			return NULL;
-		}
-		arg = newstringobject(name);
-		/*... and call it */ 
-		res = call_object(func,arg);
-		DECREF(arg);
-		DECREF(func);
+		res = call_object(func, args);
+		DECREF(args);
 	}
 	return res;
 }
@@ -543,13 +445,6 @@
 	object *v;
 {
 	object *ac;
-	if (name[0] == '_' && name[1] == '_') {
-		int n = strlen(name);
-		if (name[n-1] == '_' && name[n-2] == '_') {
-			err_setstr(TypeError, "read-only special attribute");
-			return -1;
-		}
-	}
 	ac = dictlookup(inst->in_dict, name);
 	if (ac != NULL && is_accessobject(ac))
 		return setaccessvalue(ac, getowner(), v);
@@ -570,49 +465,31 @@
 	char *name;
 	object *v;
 {
-	object *ac, *func;
-	classobject *class;
-	char* setattrname;
-	/* I think I saw something in the news, that deletion of an attribute */
-	/* is done by setattr with the value being NULL. */
-	/* Let's be prepared for this case :-)*/
-	if (v != NULL)
-		setattrname = "__setattr__";
-	else
-		setattrname = "__delattr__";
-		   
-	/* Here is the only performance loss: */
-	/* We have to check if there is a method __setattr__.*/
-	/* Only class can have a __setattr__ because it's forbidden to */
-	/* assign to self.__setattr__.*/
-	/* So, lets do a class_lookup which is (hopefully) cheap */
-	class = NULL;
-	func = class_lookup(inst->in_class, setattrname, &class);
-	if (func == NULL) {
-		/* Call the original instance_setattr */
-		return instance_setattr1(inst,name,v);
-	} else {
-		object *arg, *res;
-		/* class_lookup did'nt REF(func) - so we won't UNREF(func). */
-		/* Let's get the function (could be optimized....) */
-		func = instance_getattr(inst,setattrname);
-		if (func == 0)
-			return -1;
-		/* Deleting an attribute is done by v==NULL */
-		if (v == NULL)
-			/* __delattr__ has only one argument: the name */
-			arg = mkvalue("s",name);
-		else
-			arg = mkvalue("(sO)",name,v);
-		res = call_object(func,arg);
-		DECREF(func);
-		DECREF(arg);
-		if (res == NULL) {
-			/* Oops, something went wrong :-( */
+	object *func, *args, *res;
+	if (name[0] == '_' && name[1] == '_') {
+		int n = strlen(name);
+		if (name[n-1] == '_' && name[n-2] == '_') {
+			err_setstr(TypeError, "read-only special attribute");
 			return -1;
 		}
-		DECREF(res);
 	}
+	if (v == NULL)
+		func = inst->in_class->cl_delattr;
+	else
+		func = inst->in_class->cl_setattr;
+	if (func == NULL)
+		return instance_setattr1(inst, name, v);
+	if (v == NULL)
+		args = mkvalue("(Os)", inst, name);
+	else
+		args = mkvalue("(OsO)", inst, name, v);
+	if (args == NULL)
+		return -1;
+	res = call_object(func, args);
+	DECREF(args);
+	if (res == NULL)
+		return -1;
+	DECREF(res);
 	return 0;
 }
 
@@ -1107,7 +984,7 @@
 	(binaryfunc)instance_div, /*nb_divide*/
 	(binaryfunc)instance_mod, /*nb_remainder*/
 	(binaryfunc)instance_divmod, /*nb_divmod*/
-	(binaryfunc)instance_pow, /*nb_power*/
+	(ternaryfunc)instance_pow, /*nb_power*/
 	(unaryfunc)instance_neg, /*nb_negative*/
 	(unaryfunc)instance_pos, /*nb_positive*/
 	(unaryfunc)instance_abs, /*nb_absolute*/