Live data from Hacker News

Wield Python's super() like a Jedi

rhettinger.wordpress.com

41–50 of 67 posts

Re: Wield Python's super() like a Jedi

#42
post #6

how does the runtime performance of super() compare to the hardcoding method? (from your example, using dict.__setitem__ as opposed to super().__setitem__ )

In CPython, calling super() has about the same cost as calling any other builtin like len() or int(). The MRO itself is precomputed and stored in inst.__class__.__mro__. Contrasting dict.__setitem__ with super().__setitem__, the latter adds one function call. In addition, both forms require a builtin lookup and an attribute lookup. In PyPy, much of the overhead of builtin lookups, function calls, and attribute lookup…

Unfortunately on PyPy super is less efficient than refering directly to the parent classes method, however it's fixable (and will be fixed).

Re: Wield Python's super() like a Jedi

#44
post #24

Personally I'm not in favor of enforcing such strict conventions, especially in a dynamic language like Python. Also isn't this pattern he repeats throughout: class Shape: def __init__(self, **kwds): self.shapename = kwds.pop('shapename') super().__init__(**kwds) Better written like this? class Shape: def __init__(self, shapename=None, **kwds): self.shapename = shapename super().__init__(**kwds) It seems like there a…

These two aren't equivalent, the first example requires the shapename keyword arg, raising a KeyError when it wasn't specified

Re: Wield Python's super() like a Jedi

#45
post #44
post #24

Personally I'm not in favor of enforcing such strict conventions, especially in a dynamic language like Python. Also isn't this pattern he repeats throughout: class Shape: def __init__(self, **kwds): self.shapename = kwds.pop('shapename') super().__init__(**kwds) Better written like this? class Shape: def __init__(self, shapename=None, **kwds): self.shapename = shapename super().__init__(**kwds) It seems like there a…

These two aren't equivalent, the first example requires the shapename keyword arg, raising a KeyError when it wasn't specified

That's true. The second one might be better written as:

  def __init__(self, shapename, **kwds):
Or, in Python 3:

  def __init__(self, *, shapename, **kwds):
(making shapename a required keyword-only argument)

Re: Wield Python's super() like a Jedi

#46
post #44

Earlier quoted context omitted.

These two aren't equivalent, the first example requires the shapename keyword arg, raising a KeyError when it wasn't specified

That's true. The second one might be better written as: def __init__(self, shapename, **kwds): Or, in Python 3: def __init__(self, *, shapename, **kwds): (making shapename a required keyword-only argument)

  def __init__(self, shapename, **kwds):
is not better written; it allows shapename to be passed positionally which makes cooperative inheritance fragile.

Re: Wield Python's super() like a Jedi

#47
The "kwds" technique is actually something I came up with independently to solve a different problem when I was using PyGame: ridiculously long argument lists when constructing sprites. In this case it significantly increased the flexibility and brevity of the code, although perhaps with a more complicated inheritance tree it wouldn't be worth it.

Nice to see this pattern being acknowledged somewhere else; I thought I was the only one that did that.

Re: Wield Python's super() like a Jedi

#49

Earlier quoted context omitted.

That's true. The second one might be better written as: def __init__(self, shapename, **kwds): Or, in Python 3: def __init__(self, *, shapename, **kwds): (making shapename a required keyword-only argument)

def __init__(self, shapename, **kwds): is not better written; it allows shapename to be passed positionally which makes cooperative inheritance fragile.

The version that I was rewriting:

  def __init__(self, shapename=None, **kwds):
also allows that.

Re: Wield Python's super() like a Jedi

#50

Earlier quoted context omitted.

In CPython, calling super() has about the same cost as calling any other builtin like len() or int(). The MRO itself is precomputed and stored in inst.__class__.__mro__. Contrasting dict.__setitem__ with super().__setitem__, the latter adds one function call. In addition, both forms require a builtin lookup and an attribute lookup. In PyPy, much of the overhead of builtin lookups, function calls, and attribute lookup…

Unfortunately on PyPy super is less efficient than refering directly to the parent classes method, however it's fixable (and will be fixed).

Do you have some sort of timing measure?
Post reply on HN