On Sat, May 26, 2018 at 09:39:14AM +0200, Michael Lohmann wrote: > [Steven D'Aprano] > > obj = Aardvark(27, spam=3, eggs=5, cheese=True) > > > > So you look up help(Aardvark), and it tells you that the signature is > > > > Aardvark.__init__(self, foo) > > > > What the hell? If Aardvark.__init__ only takes a single argument > > This is wrong! This would at some point down the line throw an error > TypeError: __init__() got an unexpected keyword argument 'eggs‘
What makes you say that? Since the kwargs are passed on to the super().__init__ call, the eggs argument is passed onto the super class of Aardvark. What makes you so certain that Aardvark's parent (or grandparent, or great-grandparent...) doesn't take a parameter "eggs"? Considering that *I* made this example up, it is a bit rich for you to tell me that "eggs" isn't used. Of course it is used, by one of the superclasses. That's why it was provided. > (or at some point **kwargs are being accepted and not passed on to > super which would be terrible on its own). No, it is a standard technique to collect keyword arguments, process those your class cares about, and pass the rest on to super(). Eventually the class second from the top (the class which inherits directly from object) MUST NOT pass those arguments to super, since object doesn't accept any arguments: you can't keep passing arguments up the MRO all the way to the top. At one point or another, each argument must be used and discarded. > The whole point I was trying to make is: If it doesn’t make any sense > to init a class with **kwargs: why write down that it would (or even > **could**) accept them? If your class doesn't accept **kwargs, then don't put **kwargs in the parameter list. > Shouldn’t the init tell you something like 'If > you instantiate this class then this is everything you can give me'? The way to do that is to write the __init__ of the class that only takes the parameters you want. > Well, right now in addition it says 'Just give me anything with > keywords‘. Only if you intentionally add **kwargs to the parameter list. Why are you putting **kwargs in the parameter list if you don't want to accept them? > [Carl Smith] > > By using **kargs in the constructor and the call > > to `super`, you are indicating that the signature passes through > > But can you be certain? Couldn’t someone have just used a > `kargs.pop('eggs')`? "Somebody"? Who? It's my class. If "somebody" used kwargs.pop('eggs') it must have been me. If I did it, it means that my class wants to consume the eggs parameter and NOT pass it on. > You could argue that they probably wouldn’t > have done so. But for making automated documentation it probably would > be useful to make sure it didn’t happen. I don't understand this comment one bit. > I think that (as Raymond Hettinger once said) 'super is super', but > can’t you make it a bit smarter with telling it: 'Hey - If you don’t > expect 'eggs', keep calm, it probably (or rather certainly) wasn’t > meant for you so just pass it on to your super'. The way we do that is by explicitly collecting **kwargs and explicitly passing it on to the super call. I don't think I understand the scenario you have in mind. Here is what I have in mind: class Foo: def __init__(self, spam): self.spam = spam # this is a null-op, so it could be left out super().__init__() # calls object.__init__ which does nothing class Bar(Foo): def __init__(self, eggs, **kwargs): self.eggs = eggs super().__init__(**kwargs) class Baz(Bar): def __init__(self, cheese, **kwargs): self.cheese = cheese super().__init__(**kwargs) class Aardvark(Baz): def __init__(self, myarg, **kwargs): self.myarg = myarg super().__init__(**kwargs) obj = Aardvark(27, spam=3, eggs=5, cheese=True) What situation do you have in mind? -- Steve _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/