Hi, do you have an opinion on the following?

Wouldn't it be nice to define classes via a simple constructor function (as below) instead of a conventional class definition?

conventional:
    
    class MyClass(ParentClass):
      
def __init__(x):
        
self._x = x
      
def my_method(y):
        z 
= self._x + y
        
return z


proposed:

    def MyClass(x):
      
self = ParentClass()
      
def my_method(y):
        z 
= x + y
        
return z
      
self.my_method = my_method  # that's cumbersome (see comments below)
      
return self


Here are the pros and cons I could come up with for the proposed method:

(+) Simpler and more explicit.

(+) No need to create attributes (like `self._x`) just to pass something from `__init__` to another method.

(+) Default arguments / annotations for methods could be different for each class instance. Adaptive defaults wouldn't have to simulated with a None.

(+) Class/instance level imports would work.

(-/+) 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).

(-/+) 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.

(-) 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:
 
    def MyClass(x):
      
self = ParentClass()
      
def self.my_method(y):
        z 
= x + y
        
return z
      
return self


or alternatively multiline lambdas:

    def MyClass(x):
      
self = ParentClass()
      
self.my_method = (y):
        z 
= x + y
        
return z
      
return self


Cheers,

Simon