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" <simonramst...@gmail.com>: > Hi, thanks a lot for your feedback! > > On Sun, May 14, 2017, 00:54 Brendan Barnwell <brenb...@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@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@python.org > https://mail.python.org/mailman/listinfo/python-ideas > Code of Conduct: http://python.org/psf/codeofconduct/ > >
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/