]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Yet another version (by me) of __getattr__ etc.
authorGuido van Rossum <guido@python.org>
Mon, 5 Sep 1994 07:32:29 +0000 (07:32 +0000)
committerGuido van Rossum <guido@python.org>
Mon, 5 Sep 1994 07:32:29 +0000 (07:32 +0000)
Objects/classobject.c

index 96011810e08d7d8f7f506c8ef5e769a47a5ed0dd..8b7e4dad649e5baade048b48dd860d5b77427059 100644 (file)
@@ -29,6 +29,10 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #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 @@ newclassobject(bases, dict, name)
 {
        int pos;
        object *key, *value;
-       classobject *op;
+       classobject *op, *dummy;
        if (bases == NULL) {
                bases = newtupleobject(0);
                if (bases == NULL)
@@ -55,6 +59,12 @@ newclassobject(bases, dict, name)
        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 @@ issubclass(class, base)
 
 /* Instance objects */
 
-static object *instance_getattr PROTO((instanceobject *, char *));
-
 static int
 addaccess(class, inst)
        classobject *class;
@@ -285,7 +293,7 @@ newinstanceobject(class, arg)
                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 @@ instance_dealloc(inst)
           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 @@ instance_dealloc(inst)
        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 @@ instance_getattr(inst, name)
        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);
-               }
-               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 && (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;
+                       }
                }
-       }
-       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 @@ instance_setattr1(inst, name, v)
        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 @@ instance_setattr(inst, name, v)
        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 @@ static number_methods instance_as_number = {
        (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*/