Guido's new method definition idea
Lie Ryan
lie.1296 at gmail.com
Mon Dec 8 06:16:46 EST 2008
On Sun, 07 Dec 2008 18:27:21 +0100, Andreas Waldenburger wrote:
> On Sat, 6 Dec 2008 23:21:04 -0800 (PST) Lie <Lie.1296 at gmail.com> 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).
More information about the Python-list
mailing list