News for hackers. Stuff that matters.
Re:Python's super considered harmful by cturner on Tuesday December 28, 2010 @07:35AM (#2045304)
I think classical-inheritance subclassing is itself harmful. Subclassing creates less flexible software than other approaches, and creates a need for lots of boilerplate.

This issue - super in python - drives many new python programmers crazy. However, I suspect most seasoned devs never think about it.

These days I never subclass or feel like I want to. Occasionally I'll use 'duck' typing where I would have subclassed in the past but I find that I rarely even need that. The desire to use classes like this sets off an alarm in my head that I'm making my code too complicated.

You do a lot of subclassing in Java. Java steers you there because it's so onerous to use dictionaries and arrays/lists/tuples. The syntax for these structures is simpler in python, and so they're more commonly-used.

Subclassing is particularly important for creating frameworks in java. You build your world with packages, class hierarchies and 'bean' style objects. Whereas in python you tend to abstract by module - sets of statics, functions and lightweight structures.

I believe python would be stronger still had it had removed subclassing altogether, and instead taken the prototype approach. In prototype languages there's no such thing as a class. Everything is cloned off an original master object. Functions and properties are tapped into the clone. Iolanguage has many of these advantages but is far slower, lacks the reach of python's standard library and (I think) also lacks python's awesome list-comprehension syntax.

Someone with better articulation than me could generate blog traffic for themselves by creating a pithy post about the difference in style between java and python, and why subclassing is unpythonic. Then we could link to it when these issues come up.

Re:Python's super considered harmful by limmeau on Tuesday December 28, 2010 @09:08AM (#2045463)
I don't see much difference between a duck-typed language in which callables with capitalized name are just expected to produce objects which obey a certain duck type, and a prototype language.

The problem to which super is a (general and tricky) solution is the consequences of multiple class inheritance rather than class inheritance. A single-inheritance super could be realized in a less tricky way.

Re:Python's super considered harmful by cturner on Tuesday December 28, 2010 @09:44AM (#2045568)

    > I don't see much difference [..]
Agree, there's not much. But I have some scenarios in mind where I prefer the prototype approach.

1) Inline classes

A pattern I sometimes use involves creating an object to maintain state before a for loop. Example scenario: parsing characters as they come in over a network line. Say the data has qutation blocks that create nesting situtaion. You want to support both ' and " blocks.

It's a simple situation. You want an object that will store some kind of mode for what scope you're in at the moment, and you'll be accumulating the structure you're parsing. [1] You might want the object to have a render(self) method as well, to dump the data once you've parsed it.

In io you can just say "Make me an object that does this". In python you declare a class, and then instantiate an instance of it. It's needless to create the class - there is absolutely only one time that I'm going to build this thing. [2]

You could create a syntax that worked like python, but had a syntax that addressed this without technically being a prototype language.

2) Adding functions to existing objects

In python there is ugliness involved in tapping a new function onto an existing object. Python's a bit confusing here partly because of the way self works. When I encounter this in python I usually do a lambda trick to make the function a member of the object, and then I'll have some method on the object that will refer to it. The equivalent in io is more straightforward.

    > A single-inheritance super could be realized in a less
    > tricky way.
True. I have and will never use multiple inheritance in python and would prefer the simple syntax that would be made possible with single inheritance.

I remain interested in this broader issue of - is class-based inheritance a good thing at all?

==

[1] In python you have to use a structure for this, because once you're in the 'for' loop, it won't let you rebind variables outside the scope of the for loop, only modify them.

I haven't played with 'inline' yet.

[2] You could also use a dictionary, but I think that's a bit more verbose. An object is just what I want in these situations.

Re:Python's super considered harmful by limmeau on Tuesday December 28, 2010 @10:34AM (#2045679)
1) Good example for a one-off object implementation; however, creating a one-off class and then an instance is just one more line.

2) Actually, I don't mind if adding methods to other developers' objects is hard; it always seemed to me like a dirty hack.

Re:Python's super considered harmful by steveklabnik on Tuesday December 28, 2010 @11:55AM (#2045931)
In ruby, #2 is as simple as

    num = 42

    def num.to_whatever
      "whatever"
    end

    num.to_whatever # => 42
    41.to_whatever # => NoMethodError
I agree with my sibling, though. It might be better that this is harder in Python. It's a bad idea, generally.
Re:Python's super considered harmful by btilly on Tuesday December 28, 2010 @12:33PM (#2046055)
For #1 you can just use a closure.

For #2, the method documented in http://stackoverflow.com/questions/972/adding-a-method-to-an... doesn't seem so bad to me.

  object.methodname = new.instancemethod(function, object, class)
It may be deprecated. But it still works.
Re:Python's super considered harmful by cturner on Tuesday December 28, 2010 @01:22PM (#2046217)

    > For #1 you can just use a closure.
I don't think that will work. See the discussion about rebinding in the post or elsewhere in the thread.
Re:Python's super considered harmful by btilly on Tuesday December 28, 2010 @01:41PM (#2046286)
It is unclear to me what you think doesn't work. A closure can easily store state. As you yourself demonstrate in your rebinding example, you can store and mutate scope if you use a mutable datastructure (like a list) to avoid rebinding problems.

Perhaps if you gave an example of what you think doesn't work, I might understand your point.

Re:Python's super considered harmful by masklinn on Tuesday December 28, 2010 @12:16PM (#2045998)
> In io you can just say "Make me an object that does this". In python you declare a class, and then instantiate an instance of it. It's needless to create the class - there is absolutely only one time that I'm going to build this thing. [2]

You can create classes inline via `type`, and Python 2.6 has named tuples which are basically record types. You could also create a one-off class onto which you'd graft attributes as needed:

    >>> class Object(object): pass
    … 
    >>> a1 = Object()
    >>> a1.a = 3
    >>> a1.b = 'foo'
    >>> a2 = Object()
    >>> a2.stuff = 42
you can even use `copy.copy` (or `copy.deepcopy`) on these to have something prototypey:

    >>> a3 = copy.copy(a2)
    >>> a2.stuff
    42
    >>> a3.stuff
    42
    >>> a3.stuff = 43
    >>> a2.stuff
    42
    >>> a3.stuff
    43

> You could also use a dictionary, but I think that's a bit more verbose.

By about 4 characters per key access.

> In python there is ugliness involved in tapping a new function onto an existing object. […] When I encounter this in python I usually do a lambda trick to make the function a member of the object

What lambda trick? Why not just create a (bound) instance method from your function and graft that onto your object? Granted it's not going to be as sexy as doing so in IO, but it takes all of one line:

    >>> def foo(self): print 'Instance method of', self
    … 
    >>> # naïve version, not going to work as it doesn't bind the function to the instance, it just sets a function as a member of the object
    >>> a3.foo = foo
    >>> a3.foo()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: foo() takes exactly 1 argument (0 given)
    >>> a3.foo = types.MethodType(foo, a3, Object)
    >>> a3.foo()
    Instance method of <__main__.Object object at 0x1004cdf50>
> I have and will never use multiple inheritance in python and would prefer the simple syntax that would be made possible with single inheritance.

If you use single inheritance always, you can just get rid of `super` altogether: just call the relevant method on your superclass.

> [1] In python you have to use a structure for this, because once you're in the 'for' loop, it won't let you rebind variables outside the scope of the for loop, only modify them.

I hope I misunderstand what you mean, because what I'm reading here is downright wrong: Python only has function-level scoping (and a special scope for listcomps, but that's a different issue) so any binding you create or modify within a for loop (or a `with` statement, or an `if` or whatever else you may think of) will be visible from outside the block:

    >>> a
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'a' is not defined
    >>> for i in range(1):
    ...     a = i
    ... 
    >>> a
    0
And of course, you can rebind existing variables just fine:

    >>> for i in range(2):
    ...     a = i
    ... 
    >>> a
    1
did I miss something?
Re:Python's super considered harmful by cturner on Tuesday December 28, 2010 @01:07PM (#2046164)

    > did I miss something?
In your examples you're binding or rebinding to vars in the current scope. The issue is rebinding vars outside of the current scope.

Perhaps this code demonstates what I'm getting at.

    def my_function():
        a = 1
        def modify_a():
            a = 2
        modify_a()
        print a # prints 1
        #
        b = [1]
        def modify_b():
            b = 2
        modify_b()
        print b[0] # prints 1
        #
        c = [1]
        def modify_c():
            c[0] = 2
        modify_c()
        print c[0] # prints 2

    my_function()
Re:Python's super considered harmful by masklinn on Tuesday December 28, 2010 @01:17PM (#2046197)
This is clearer, but it has absolutely nothing to do with `for` loops (which is why your statement utterly confused me) and everything to do with Python's broken scoping in general: Python 2 gives no writing access to lexical scopes between global and local (Python 3 added a new keyword, `nonlocal`, which is used in the same manner as `global` to set a binding as writable in a parent scope).
Re:Python's super considered harmful by stcredzero on Tuesday December 28, 2010 @11:21AM (#2045824)
Iolanguage has many of these advantages but is far slower, lacks the reach of python's standard library and (I think) also lacks python's awesome list-comprehension syntax.

Lua is prototype based. It's also quite fast. What if we ported the Python standard library and added list-comprehension?

[deleted]
Re:Python's super considered harmful by stcredzero on Tuesday December 28, 2010 @01:16PM (#2046192)
Well, there's already Lunatic Python, so any Python libraries you lack can just be called from a hosted Python VM instance. Also, I think It's possible to add comprehension-like syntax to Lua already.