[Python-ideas] JavaScript-Style Object Creation in Python (using a constructor function instead of a class to create objects)

Antoine Rozo antoine.rozo at gmail.com
Sun May 14 03:57:25 EDT 2017


How do you call methods from superclass, like super in classic style ?

2017-05-14 9:45 GMT+02:00 Stephan Houben <stephanh42 at gmail.com>:

> FWIW, Javascript itself is moving away from this syntax in favour of a
> more Python-like syntax based on the 'class' keyword. This was introduced
> in EcmaScript 2015.
>
> Stephan
>
> Op 14 mei 2017 09:35 schreef "Simon Ramstedt" <simonramstedt at gmail.com>:
>
> Hi, thanks a lot for your feedback!
>>
>> On Sun, May 14, 2017, 00:54 Brendan Barnwell <brenbarn at brenbarn.net>
>> wrote:
>>
>>> On 2017-05-13 21:07, Simon Ramstedt wrote:
>>> > Hi, do you have an opinion on the following?
>>>
>>>         My general opinion is that imitating JavaScript is almost always
>>> a bad
>>> idea.  :-)
>>>
>>> > Wouldn't it be nice to define classes via a simple constructor function
>>> > (as below) instead of a conventional class definition?
>>> >
>>> > *conventional*:
>>> > |
>>> > classMyClass(ParentClass):
>>> > def__init__(x):
>>> > self._x=x
>>> > defmy_method(y):
>>> >          z=self._x+y
>>> > returnz
>>> > |
>>> >
>>> >
>>> > *proposed*:
>>> >
>>> > |
>>> > defMyClass(x):
>>> > self=ParentClass()
>>> > defmy_method(y):
>>> >          z=x+y
>>> > returnz
>>> > self.my_method=my_method # that's cumbersome (see comments below)
>>> > returnself
>>> > |
>>> >
>>> >
>>> > Here are the pros and cons I could come up with for the proposed
>>> method:
>>> >
>>> > (+) Simpler and more explicit.
>>>
>>>         I don't really see how that's simpler or more explicit.  In one
>>> respect
>>> it's clearly less explicit, as the "self" is implicit.
>>>
>>> > (+) No need to create attributes (like `self._x`) just to pass
>>> something
>>> > from `__init__` to another method.
>>>
>>>         Attributes aren't just for passing things to other methods.
>>> They're
>>> for storing state.  In your proposed system, how would an object mutate
>>> one of its own attributes?  It looks like "x" here is just stored in a
>>> function closure, which wouldn't allow easy mutation.  Also, how would
>>> another object access the attribute from outside (as we currently do
>>> with self.x)?  You can say we'd only use this new attribute-free
>>> approach when we want to pass a constructor argument that's used but
>>> never mutated or accessed from outside, but that severely restricts the
>>> potential use cases, and all it saves you is typing "self".
>>>
>>
>> Attributes could be added to self just as in conventional classes if they
>> are needed.
>>
>>
>>>         Relatedly, how is ParentClass itself defined?  I don't see how
>>> you
>>> could bootstrap this without having a real class at the bottom of it
>>> somehow (as your test script in fact does).
>>>
>>
>> You could bootstrap with an object base class/constructor just as normal
>> classes inherit from object. Also the normal class system should remain in
>> any case in order not to break every python library.
>>
>>>
>>> > (+) Default arguments / annotations for methods could be different for
>>> > each class instance. Adaptive defaults wouldn't have to simulated with
>>> a
>>> > None.
>>>
>>>         That seems as likely to be a negative as a positive.  Having
>>> different
>>> instances with different default values could be confusing.  This would
>>> even allow different instances to define totally different methods (with
>>> if-logic inside the function constructor), which would definitely be
>>> confusing.
>>>
>>
>> Different default values for different instances are a corner case but
>> they are already happening by setting default to None. Defining
>> different methods for different instances wouldn't be good but that is also
>> possible with conventional classes (by adding functions to self in
>> __init__).
>>
>> > (+) Class/instance level imports would work.
>>>
>>>         How often is that really needed?
>>>
>>
>> True, usually it doesn't matter. But when using big packages like
>> tensorflow that take several seconds to load it can be annoying. Its always
>> loaded when importing any library that uses it internally, because of
>> module level imports that should be class/instance level. Even if we just
>> wanted to do --help on the command line and needed that library before
>> argparse for some reason.
>>
>> > (-/+) Speed: The `def`-based objects take 0.6 μs to create while the
>>> > `class`-based objects take only 0.4 μs. For method execution however
>>> the
>>> > closure takes only 0.15 μs while the proper method takes 0.22 μs
>>> (script
>>> > <https://gist.github.com/rmst/78b2b0f56a3d9ec13b1ec6f3bd50aa9c>).
>>>
>>>         I don't think you can really evaluate the performance impact of
>>> this
>>> alternative just based on a trivial example like that.
>>>
>>> Agree, I don't know really how well this would perform.
>>>
>>
>> > (-/+) Checking types: In the proposed example above the returned object
>>> > wouldn't know that it has been created by `MyClass`. There are a couple
>>> > of solutions to that, though. The easiest to implement would be to
>>> > change the first line to `self = subclass(ParentClass())` where the
>>> > subclass function looks at the next item in the call stack (i.e.
>>> > `MyClass`) and makes it the type of the object. Another solution would
>>> > be to have a special rule for functions with capital first letter
>>> > returning a single object to append itself to the list of types of the
>>> > returned object. Alternatively there could be a special keyword e.g.
>>> > `classdef` that would be used instead of `def` if we wouldn't want to
>>> > rely on the name.
>>>
>>>         Those special rules sound very hackish to me.
>>
>>
>>> > (-) The current syntax for adding a function to an object is
>>> > cumbersome.  That's what is preventing me from actually using the
>>> > proposed pattern. But is this really the only reason for not using it?
>>> > And if so, wouldn't that be a good argument for enabling something like
>>> > below?
>>> > *
>>> > *
>>> > *attribute function definitions*:
>>> > |
>>> > defMyClass(x):
>>> > self=ParentClass()
>>> > defself.my_method(y):
>>> >          z=x+y
>>> > returnz
>>> > returnself
>>> > |
>>> >
>>> >
>>> > or alternatively*multiline lambdas*:
>>> >
>>> > |
>>> > defMyClass(x):
>>> > self=ParentClass()
>>> > self.my_method=(y):
>>> >          z=x+y
>>> > returnz
>>> > returnself
>>> > |
>>>
>>>         To be honest, from all your examples, I don't really see what
>>> the point
>>> is.  It's a different syntax for doing some of the same things the
>>> existing class syntax does, while providing no apparent way to do some
>>> important things (like mutating attributes).  I think Python's existing
>>> class syntax is simple, clear, and quite nice overall, and creating
>>> class instances by calling a function instead of a class doesn't add
>>> anything.  In fact, even JavaScript has recently added classes to allow
>>> programmers to move away from the old approach that you describe here.
>>> Also, as I alluded to above, JavaScript is so terrible in so many ways
>>> that the mere idea of imitating it inherently makes me skeptical;
>>> there's almost nothing about JavaScript's design that couldn't be done
>>> better, and most of what it does are things that Python already does
>>> better and has done better for years.  In short, I don't see any
>>> advantages at all to doing classes this way, and there are some
>>> non-negligible disadvantages.
>>>
>>
>> Interesting, didn't know that about Javascript. I also don't like
>> Javascript's prototypes very much but thought adding "JavaScript-like" to
>> the title might help explain what I meant.
>>
>> Leaving the possible replacement for classes aside, do you have an
>> opinion specifically about the following?
>>
>> def obj.my_function(a, b):
>>    ...
>>
>> as syntactic sugar for
>>
>> def my_function(a, b):
>>   ...
>>
>> obj.my_function = my_function
>>
>> In my experience this pattern comes actually up quite a bit. E.g. when
>> working with these "symbolic" machine learning frameworks like theano or
>> tensorflow. Apart from that it mixins very easy.
>>
>> What do you think are the odds of something like this actually making it
>> into the Python and if greater than 0 in which timeframe?
>>
>>
>>
>>> --
>>> Brendan Barnwell
>>> "Do not follow where the path may lead.  Go, instead, where there is no
>>> path, and leave a trail."
>>>     --author unknown
>>> _______________________________________________
>>> Python-ideas mailing list
>>> Python-ideas at python.org
>>> https://mail.python.org/mailman/listinfo/python-ideas
>>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>>
>> Thanks,
>>
>> Simon
>>
>>>
>>>
>> _______________________________________________
>> Python-ideas mailing list
>> Python-ideas at python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
>


-- 
Antoine Rozo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20170514/6862aef3/attachment.html>


More information about the Python-ideas mailing list