type(d) != type(d.copy()) when type(d).issubclass(dict)

Discussion in 'Python' started by kj, Dec 24, 2010.

  1. kj

    kj Guest

    Watch this:

    >>> class neodict(dict): pass

    ....
    >>> d = neodict()
    >>> type(d)

    <class '__main__.neodict'>
    >>> type(d.copy())

    <type 'dict'>


    Bug? Feature? Genius beyond the grasp of schlubs like me?

    ~kj
    kj, Dec 24, 2010
    #1
    1. Advertising

  2. On Fri, Dec 24, 2010 at 1:52 PM, kj <> wrote:
    > Watch this:
    >
    >>>> class neodict(dict): pass

    > ...
    >>>> d = neodict()
    >>>> type(d)

    > <class '__main__.neodict'>
    >>>> type(d.copy())

    > <type 'dict'>
    >
    >
    > Bug?  Feature?  Genius beyond the grasp of schlubs like me?

    copy, here, is a dict method. It will create a dict.
    If you really need it, you could try this:

    import copy
    class neodict(dict):
    def copy(self):
    return copy.copy(self)

    d = neodict()
    print type(d)
    dd = d.copy()
    print type(dd)
    David Robinow, Dec 24, 2010
    #2
    1. Advertising

  3. On Sat, 25 Dec 2010 15:58:35 +0000, Duncan Booth wrote:

    > kj <> wrote:
    >
    >> Watch this:
    >>
    >>>>> class neodict(dict): pass

    >> ...
    >>>>> d = neodict()
    >>>>> type(d)

    >><class '__main__.neodict'>
    >>>>> type(d.copy())

    >><type 'dict'>
    >>
    >>
    >> Bug? Feature? Genius beyond the grasp of schlubs like me?

    >
    > Feature.


    I'd say it is neither, and call it a bloody nuisance that nevertheless
    has some justification.


    > In (almost?) all cases any objects constructed by a subclass of a
    > builtin class will be of the original builtin class. So, for example,
    > subclass a string and concatenating your subclassed objects still
    > produces a string.


    Yes, and the consequence is that any serious subclass must overload every
    method which returns a new instance, otherwise your new subclass doesn't
    "stick" -- you find it being replaced by the builtin as soon as you start
    doing something useful with it.

    This is especially a nuisance for subclasses of (say) float, where you
    end up writing heaps of boilerplate like this:

    class MyFloat(float):
    def __add__(self, other):
    return self.__class__(super(MyFloat, self).__add__(other))
    # and the same for __mul__, __sub__, __rsub__, __pow__, ...


    > This is reasonable behaviour as for builtin classes performance is more
    > important than fully implementing polymorphism. If you want to subclass
    > a builtin class you need to be aware of this and override the behaviour
    > where it matters.


    Yes, but I think builtins could probably afford one extra identity check.
    Something like this:


    # Pseudocode
    if type(self) is builtin type:
    do exactly what is done now
    else:
    do something slower, but kinder for superclasses


    For all I know, the slower branch might be something as simple as calling
    the C equivalent of type(self)(arg).



    --
    Steven
    Steven D'Aprano, Dec 25, 2010
    #3
  4. kj

    John O'Hagan Guest

    On Sat, 25 Dec 2010, Steven D'Aprano wrote:
    > On Sat, 25 Dec 2010 15:58:35 +0000, Duncan Booth wrote:
    > > kj <> wrote:
    > >> Watch this:
    > >>>>> class neodict(dict): pass
    > >>
    > >> ...
    > >>
    > >>>>> d = neodict()
    > >>>>> type(d)
    > >>
    > >><class '__main__.neodict'>
    > >>
    > >>>>> type(d.copy())
    > >>
    > >><type 'dict'>
    > >>
    > >> Bug? Feature? Genius beyond the grasp of schlubs like me?

    > >
    > > Feature.

    >
    > I'd say it is neither, and call it a bloody nuisance that nevertheless
    > has some justification.
    >
    > > In (almost?) all cases any objects constructed by a subclass of a
    > > builtin class will be of the original builtin class. So, for example,
    > > subclass a string and concatenating your subclassed objects still
    > > produces a string.

    >
    > Yes, and the consequence is that any serious subclass must overload every
    > method which returns a new instance, otherwise your new subclass doesn't
    > "stick" -- you find it being replaced by the builtin as soon as you start
    > doing something useful with it.
    >
    > This is especially a nuisance for subclasses of (say) float, where you
    > end up writing heaps of boilerplate like this:
    >
    > class MyFloat(float):
    > def __add__(self, other):
    > return self.__class__(super(MyFloat, self).__add__(other))
    > # and the same for __mul__, __sub__, __rsub__, __pow__, ...

    [...]

    I've occasionally wished I could just:

    import builtin_subclass_fixer

    class MyList(list):
    def __init__(self):
    builtin_subclass_fixer.fix(self)
    ...
    ...

    to automatically ensure that new objects returned by MyList methods are of the
    same class without my having to identify and override every such method.

    IMO one of the benefits of subclassing is that you can just "bolt on"
    additional behaviour without having to know all the inner workings of the
    superclass, a benefit that is somewhat defeated by this behaviour of builtins.

    OTOH - not that I advocate nuisance as a deterrent - the nuisance factor of
    this has encouraged me to look harder for simpler solutions. Most of the time
    I've realised I didn't really need to subclass at all, and thus avoided "lazy
    subclassing".

    John
    John O'Hagan, Dec 26, 2010
    #4
  5. kj

    kj Guest

    "John O'Hagan" <> writes:

    >IMO one of the benefits of subclassing is that you can just "bolt on"
    >additional behaviour without having to know all the inner workings of the
    >superclass, a benefit that is somewhat defeated by this behaviour of builtins.


    I agree. I've read the old post/articles by GvR and other over
    how great it will be now that one can subclass Python builtin types
    like any other class (GvR even gives explicit examples of this
    luscious possibility in his paper on type/class unification). But
    now I'm discovering so many caveats, exceptions, and gotchas about
    subclassing builtins that I have to conclude that this much celebrated
    new capability is basically useless... Just like "readability
    counts", it is also true that "conceptual clarity" counts, and
    treating builtins as classes in Python is the most obfuscated design
    I've ever seen.

    UserDict, come back, all is forgotten!

    ~kj
    kj, Dec 26, 2010
    #5
  6. kj

    kj Guest

    In <Xns9E59A27DEF178duncanbooth@127.0.0.1> Duncan Booth <> writes:

    >kj <> wrote:


    >> Watch this:
    >>
    >>>>> class neodict(dict): pass

    >> ...
    >>>>> d = neodict()
    >>>>> type(d)

    >><class '__main__.neodict'>
    >>>>> type(d.copy())

    >><type 'dict'>
    >>
    >>
    >> Bug? Feature? Genius beyond the grasp of schlubs like me?


    >Feature.


    >In (almost?) all cases any objects constructed by a subclass of a builtin
    >class will be of the original builtin class.



    What I *really* would like to know is: how do *you* know this (and
    the same question goes for the other responders who see this behavior
    of dict as par for the course). Can you show me where it is in
    the documentation? I'd really appreciate it. TIA!

    ~kj
    kj, Dec 26, 2010
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Green

    when does issubclass fail?

    Chris Green, Apr 16, 2004, in forum: Python
    Replies:
    1
    Views:
    299
    =?ISO-8859-1?Q?Walter_D=F6rwald?=
    Apr 20, 2004
  2. Nathan Bullock

    How do you make issubclass work

    Nathan Bullock, Sep 11, 2004, in forum: Python
    Replies:
    4
    Views:
    621
    Alex Martelli
    Sep 11, 2004
  3. Alex
    Replies:
    2
    Views:
    1,218
  4. Osmo Maatta
    Replies:
    3
    Views:
    474
    Osmo Maatta
    Aug 29, 2010
  5. kj

    issubclass(dict, Mapping)

    kj, Dec 22, 2010, in forum: Python
    Replies:
    10
    Views:
    533
Loading...

Share This Page