On Sun, 07 Dec 2008 18:27:21 +0100, Andreas Waldenburger wrote: > On Sat, 6 Dec 2008 23:21:04 -0800 (PST) Lie <[EMAIL PROTECTED]> wrote: > >> I think we have to test this on newbies. [snip] >> > Now that's talking like a programmer! > > Ideas on how such a survey could be conducted? Anyone? > > >> If this dead horse is revived because of that reason, then I'd go with >> changing the error message to something that is less confusing to >> newbies[1]. > + googol > > >> I remember being tripped with the (thinking that python miscounted the >> number of argument) when I was new. This has the advantage of backward >> compatibility and no syntax change, just less misleading error message. >> >> [1] anything could work, but I like this one: (c is an instance of >> class C) >> if the code is: c.foo(...), Error: "TypeError: c.foo() takes exactly 3 >> argument" >> while if the code is: C.foo(...), Error: "C.foo() takes exactly 4 >> arguments" >> You can implement c.foo as a curried C.foo function, catch C.foo's >> TypeError exception then reraise it as c.foo exception. > I'm not sure that I'd find that less confusing. Because a c.foo() *does* > take four arguments, not three. It's just that the first one is implicit > (Right?).
It's not implicit, we explicitly pass c (the object instance), although not in the argument list. So c.foo takes 3 arguments while C.foo takes 4 arguments. In other words: from functools import partial c = C() -> c.attr = partial(C.attr, c) Note the error message I gave: "TypeError: c.foo() takes exactly 3 arguments" "TypeError: C.foo() takes exactly 4 arguments" There are two differences there, not only one claims to accept three and the other 4 arguments, but also the capitalization of c/C. Here is a clearer example: inst = cls() "TypeError: inst.foo() takes exactly 3 arguments" "TypeError: cls.foo() takes exactly 4 arguments" for comparison, python's current (2.5) error message is: "TypeError: foo() takes exactly 4 arguments" in addition, with this proposal we'll know how foo is being called. The following is a quick and dirty implementation of such error message. Note: There are still some unresolved problems though: 1. instance.[func name] is hardcoded, as I don't know how to get the instance's name from the instance creation itself 2. Class Invoking from class gives TypeError: foo()... instead of TypeError: Class.foo()... 3. most definitely not to be used on real application from types import MethodType import re errmess = re.compile(r'(.*?) (.*?) (\d*) (arguments?) \((\d*) given\)') def usenewexc(obj): def wrap(f): def wrap_(*args, **kargs): try: print args, kargs return f(*args, **kargs) except TypeError, e: re_mess = errmess.match(e.message) fname = re_mess.group(1) interm = re_mess.group(2) if re_mess.group(3) != '1' else 'takes' reqargs = int(re_mess.group(3)) - 1 if re_mess.group(3) ! = '1' else 'no' argue_s = re_mess.group(4) if re_mess.group(3) != '1' else 'arguments' givenargs = int(re_mess.group(5)) - 1 raise TypeError('%s.%s %s %s %s (%s given)' % ('instance', fname, interm, reqargs, argue_s, givenargs)) return wrap_ for attrname in dir(obj): attr = obj.__getattribute__(attrname) if type(attr) == MethodType: obj.__setattr__(attrname, wrap(attr)) return obj class A(object): def foo(self): print '' pass a = usenewexc(A()) A.foo(a, 2) > How about: > > "TypeError: c.foo() takes exactly 3 arguments in addition to the > implicit instance reference." > > or > > "TypeError: c.foo() takes exactly 4 arguments (5 given, including the > implicit instance reference)" > > ... or something less kludgy in that general direction. This would > explain exactly what is wrong. > > /W > > -- > My real email address is constructed by swapping the domain with the > recipient (local part). -- http://mail.python.org/mailman/listinfo/python-list