[Python-Dev] Breaking calls to object.init/new (original) (raw)

Guido van Rossum guido at python.org
Thu Mar 22 04:37:34 CET 2007


On 3/21/07, Jean-Paul Calderone <exarkun at divmod.com> wrote:

On Wed, 21 Mar 2007 15:45:16 -0700, Guido van Rossum <guido at python.org> wrote: >See python.org/sf/1683368. I'd like to invite opinions on whether it's >worth breaking an unknown amount of user code in 2.6 for the sake of >stricter argument checking for object.init and object.new. I >think it probably isn't; but the strict version could be added to 3.0 >and a warning issued in 2.6 in -Wpy3k mode. Alternatively, we could >introduce the stricter code in 2.6, fix the stdlib modules that it >breaks, and hope for the best. Opinions? >

Perhaps I misunderstand the patch, but it would appear to break not just some inadvisable uses of super(), but an actual core feature of super(). Maybe someone can set me right. Is this correct? class Base(object): def init(self, important): # Don't upcall with important because object is the base # class and its init doesn't care (or won't accept) it super(Base, self).init() self.a = important If so, what are the implications for this? class Other(object): def init(self, important): # Don't upcall with important because object is the base # class and its init doesn't care (or won't accept) it super(Other, self).init() self.b = important class Derived(Base, Other): pass

(A similar example could be given where Base and Other take differently named arguments with nothing to do with each other. The end result is the same either way, I think.) I think I understand the desire to pull keyword arguments out at each step of the upcalling process, but I don't see how it can work, since "up" calling isn't always what's going on - given a diamond, there's arbitrary side-calling, so for cooperation to work every method has to pass on every argument, so object.init has to take arbitrary args, since no one knows when their "up" call will actually hit object. Since without diamonds, naive "by-name" upcalling works, I assume that super() is actually intended to be used with diamonds, so this seems relevant. I hope I've just overlooked something. Writing this email feels very strange. Jean-Paul

There are different philosophies about the correct style for cooperative super calls.

The submitter of the bug report likes to remove "consumed" arguments and pass the others on, having something at the root that complains about any unused arguments. It has the problem that you mention: if multiple classes might be interested in the same argument they won't see it. The other style is to pass all arguments down, and let everyone cherry-pick them. The last call then just throws them away. This has the problem that misspelled arguments are silently ignored rather than being diagnosed at the point where you can do something about it.

I don't know what the "best practice" is (like Greg Ewing, I don't use either style myself) but I've got a feeling that it must be easier to solve the former problem than the latter (also I don't know that the former actually occurs in practice). When using more traditional styles, or single inheritance, it certainly makes more sense to reject excess arguments than to ignore them; the original code was clearly intending to do this, but due to the minimalist coding, it didn't catch enough.

I've pretty much made up my mind at this point that the right way forward is to be strict; in 3.0 we can afford to be strict as in the strict version of the patch, while in 2.6 we'll be less strict, but still stricter than 2.5; 2.6 in -Wpy3k mode will issue warnings for those cases where 3.0 will issue an error but 2.6 doesn't.

-- --Guido van Rossum (home page: http://www.python.org/~guido/)



More information about the Python-Dev mailing list