Live data from Hacker News

Wield Python's super() like a Jedi

rhettinger.wordpress.com

21–30 of 67 posts

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

#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 are some things about Python's which the author doesn't like, and he solves them by adding a lot of boiler plate to each of his classes. It's probably a better idea to just embrace the Python way or use a different language.

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

#25
It seems to me that the example of combining built-in dictionary classes is naively optimistic. For starters, OrderedDict, as it happens, does not use super! It calls the dict super-class methods directly. Since dict happens to be the next class in the MRO, this doesn't really matter for the purpose of this example, but I can envision a scenario where some plucky programmer inherits from both OrderedCounter and some other dict subclass, and the result doesn't work because OrderedDict does the wrong thing.

And OrderedDict isn't the only one. Maybe for some reason I would like to have an OrderedCounter where all the counts default to 42. So I do this:

  class DefaultOrderedCounter(defaultdict, OrderedCounter):
      pass
  doc = DefaultOrderedCounter(lambda: 42)
  doc.update('abracadabra')
Which results in:

  Traceback (most recent call last):
    File "", line 1, in 
    File "c:\python32\lib\collections.py", line 507, in update
      _count_elements(self, iterable)
    File "c:\python32\lib\collections.py", line 63, in __setitem__
      self.__map[key] = link = Link()
  AttributeError: 'DefaultOrderedCounter' object has no attribute '_OrderedDict__map'
Whoops! Apparently defaultdict doesn't use super either. Of course a better way to do this would be to subclass DefaultOrderedCounter and just override the __missing__ method by hand, but that's not the point.

The article goes into "How to Incorporate a Non-cooperative Class", which basically says "wrap it up in a proxy class". But that's not really going to work here, since the result would be two separate dicts, with the defaultdictwrapper methods operating on one dict, and the other methods operating on the other.

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

#26

It seems to me that the example of combining built-in dictionary classes is naively optimistic. For starters, OrderedDict, as it happens, does not use super! It calls the dict super-class methods directly. Since dict happens to be the next class in the MRO, this doesn't really matter for the purpose of this example, but I can envision a scenario where some plucky programmer inherits from both OrderedCounter and some…

Okay, I give. What's the markup for posting code snippets on this site?

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

#27

It seems to me that the example of combining built-in dictionary classes is naively optimistic. For starters, OrderedDict, as it happens, does not use super! It calls the dict super-class methods directly. Since dict happens to be the next class in the MRO, this doesn't really matter for the purpose of this example, but I can envision a scenario where some plucky programmer inherits from both OrderedCounter and some…

Okay, I give. What's the markup for posting code snippets on this site?

Put two spaces at the beginning of a line for that line to be displayed monospaced.

  Example

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

#29
Nice article, but one thing struck me when reading the code examples posted in the article: What's the use of using kwds in __init__?

    class Shape(Root):
        def __init__(self, **kwds):
            self.shapename = kwds.pop('shapename')
            super().__init__(**kwds)

    class ColoredShape(Shape):
        def __init__(self, **kwds):
            self.color = kwds.pop('color')
            super().__init__(**kwds)
I would personally just have written this somewhat similar to this:

    class Shape(Root):
        def __init__(self, shapename):
            self.shapename = shapename
            super().__init__()

    class ColoredShape(Shape):
        def __init__(self, shapename, color):
            self.shapename = shapename
            self.color = color
            super().__init__(shapename)
But then again I'm by no means what anyone could call a Python 'Jedi'. Can anyone explain to me why using kwds in this way would be better? Would it not lead to having to look up the declaration of the class for the exact names of arguments to pop() every time?

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

#30

tl;dr Just looks like super/parent like in other languages. Did i miss something from not reading this?

Some small steps in the direction of a meta-object protocol: more fine-grained control over call dispatch in a multiply-inheriting class hierarchy.
Post reply on HN