{"action":"created","issue":{"url":"https://api.github.com/repos/odlgroup/odl/issues/1061","repository_url":"https://api.github.com/repos/odlgroup/odl","labels_url":"https://api.github.com/repos/odlgroup/odl/issues/1061/labels{/name}","comments_url":"https://api.github.com/repos/odlgroup/odl/issues/1061/comments","events_url":"https://api.github.com/repos/odlgroup/odl/issues/1061/events","html_url":"https://github.com/odlgroup/odl/issues/1061","id":240712494,"number":1061,"title":"Use super(cls, self) instead of super() or hard-coded class?","user":{"login":"kohr-h","id":5030250,"avatar_url":"https://avatars1.githubusercontent.com/u/5030250?v=3","gravatar_id":"","url":"https://api.github.com/users/kohr-h","html_url":"https://github.com/kohr-h","followers_url":"https://api.github.com/users/kohr-h/followers","following_url":"https://api.github.com/users/kohr-h/following{/other_user}","gists_url":"https://api.github.com/users/kohr-h/gists{/gist_id}","starred_url":"https://api.github.com/users/kohr-h/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kohr-h/subscriptions","organizations_url":"https://api.github.com/users/kohr-h/orgs","repos_url":"https://api.github.com/users/kohr-h/repos","events_url":"https://api.github.com/users/kohr-h/events{/privacy}","received_events_url":"https://api.github.com/users/kohr-h/received_events","type":"User","site_admin":false},"labels":[{"id":353773469,"url":"https://api.github.com/repos/odlgroup/odl/labels/discussion","name":"discussion","color":"fef2c0","default":false},{"id":289000198,"url":"https://api.github.com/repos/odlgroup/odl/labels/odl%20core","name":"odl core","color":"5319e7","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2017-07-05T16:51:31Z","updated_at":"2017-07-05T20:48:59Z","closed_at":null,"body":"So far we always use e.g. `super().__init__(...)` in subclasses and get Python 2 compatibility by importing a `super` backport from the `future` library. That is, however, slow, and thus a bunch of speed-critical classes already replace this by hard-coded `ParentClass.__init__(self, ...)` calls.\r\n\r\nThis is not very pretty and particularly unfriendly towards downstream subclassers. Thus, an alternative could be to use the built-in `super` in both Python 2 and 3 and stick to the (required in Py2, redundant but valid in Py3) syntax `super(cls, self).__init__(...)`.\r\n\r\n@adler-j do you have any good test lying around to check the speed of this compared to `super` from `future` and hard-coded parents?"},"comment":{"url":"https://api.github.com/repos/odlgroup/odl/issues/comments/313222541","html_url":"https://github.com/odlgroup/odl/issues/1061#issuecomment-313222541","issue_url":"https://api.github.com/repos/odlgroup/odl/issues/1061","id":313222541,"user":{"login":"kohr-h","id":5030250,"avatar_url":"https://avatars1.githubusercontent.com/u/5030250?v=3","gravatar_id":"","url":"https://api.github.com/users/kohr-h","html_url":"https://github.com/kohr-h","followers_url":"https://api.github.com/users/kohr-h/followers","following_url":"https://api.github.com/users/kohr-h/following{/other_user}","gists_url":"https://api.github.com/users/kohr-h/gists{/gist_id}","starred_url":"https://api.github.com/users/kohr-h/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kohr-h/subscriptions","organizations_url":"https://api.github.com/users/kohr-h/orgs","repos_url":"https://api.github.com/users/kohr-h/repos","events_url":"https://api.github.com/users/kohr-h/events{/privacy}","received_events_url":"https://api.github.com/users/kohr-h/received_events","type":"User","site_admin":false},"created_at":"2017-07-05T20:48:59Z","updated_at":"2017-07-05T20:48:59Z","body":"Here are some very quick timing results.\r\n\r\nI test the following inheritance chain (not totally trivial, needs to be traversed to the top):\r\n```python\r\nclass A(object):\r\n    def __init__(self, a):\r\n        self.a = a\r\n\r\nclass B(A):\r\n    pass\r\n\r\nclass C(object):\r\n    pass\r\n\r\nclass D1(C, A):\r\n    def __init__(self, a, b):\r\n        super().__init__(a)  # Invalid in Python 2\r\n        self.b = b\r\n\r\nclass D2(C, A):\r\n    def __init__(self, a, b):\r\n        super(D2, self).__init__(a)  # Works with Python 2 and 3\r\n        self.b = b\r\n        \r\nclass D3(C, A):\r\n    def __init__(self, a, b):\r\n        A.__init__(self, a)  # Hard-coded, no MRO involved\r\n        self.b = b\r\n```\r\nRunning `%timeit d = D1(1, 2)` and equally for `D2` and `D3` give these results:\r\n\r\nPython version | `D1` (`super` magic) | `D2` (`super`, explicit args) | `D3` (hard-coded)\r\n------------------- | ----- | ------ | ------\r\n2.7, built-in `super` | :x: | 599 ns | 555 ns\r\n2.7,`super` from `future` | **7.18 µs** | 729 ns | 570 ns\r\n3.6 | 650 ns | 707 ns | 479 ns\r\n\r\nThis seems to summarize quite well the experience from the past, namely that using the backported `super` in Python 2 really gives a significant performance hit when many objects need to be created. The remaining options are more or less on par. Skipping the MRO entirely is, of course, fastest, but not really by much. And the difference `super` with and without args is probably just storage of arguments and dictionary lookups that come on top for the former.\r\n\r\nI'd say this is a viable option (given that this behavior shows up also in practice, but why shouldn't it)."}}
{"actor":{"display_login":"kohr-h"}}