Jump to content

A new Object Oriented System for Python (Kisa)

Hello everyone,

I am a Python programmer for quite a while and although Python makes development easier and faster in a lot of ways, there is an area that always seemed that was kept behind even though it was widely used by the Python community, and that thing I’m talking about is Pythons native Object Oriented System.

While Java or C# or even C++ has an Object Oriented system that support attribute type enforcement, interfaces and abstract classes, Python can somewhat provide those things, but without any enforcement at all.

That always seemed to me a shameful thing, because Python in many ways is a very powerful language, but that also makes it prone to errors. For instance, I’ve had many bugs in Python when I was trying to assign a value to the wrong attribute because I simply misspelled it’s name by one character (e.g. namee instead of name).

Another issue that seemed problematic to me is that there are a lot of repetitive tasks we do when creating classes that could be automated as well, from constructors, type enforcement, lazy attributes to the creation of getters/setters (While I’m aware of the @property decorator, I always preferred get/set methods). Granted, Python 3.7 introduced the @dataclass classes, they are very simplistic — No type enforcement, default values assignement is basic at best (You cannot call a method to assign their default values), let alone speak about lazy attributes, or final attributes.

For that reason, I’ve decided to create a new Object Oriented System for Python — Kisa. Kisa supposed to bring many improvements over Pythons native Object Oriented System and that includes:

  • Auto generated getters/setters
  • Auto generated constructors
  • Default attributes — Can be initialized from instance method
  • Lazy attributes
  • Attribute type support
  • Abstract classes
  • Interfaces
  • Enforcement of inheritance
  • Static attributes
  • Static methods
  • Attribute modifiers — Add hooks to attribute/method call before the call, around the call or after it was called
  • Allow attributes to be None or not
  • Make attributes final
  • Decide if attributes are required by the constructor or not
  • Many more

I believe Kisa can and will make development in Python faster to write, maintain, better organized, and safer.

A very basic example of a Kisa class:

import kisa

class Person(metaclass=kisa.Class):
    firstname = kisa.Info(type=str,  required=True, final=True)
    lastname = kisa.Info(type="str", required=True, final=True)
    age = kisa.Info(type=int, required=True)
    friends = kisa.Info(type=list, default=lambda: [])

    def fullname(self):
        return f"{self.firstname()} {self.lastname()}"

    def birthday(self):
        # Getter
        new_age = self.age() + 1

        # Setter
        self.age(new_age)

# # raises Exception: "firstname" is Missing in instance creation for class Person
# noam = Person()

noam = Person(firstname="Noam", lastname="Nisanov", age=22)

# raises Exception: Tried to modify a final attribute "firstname"
# noam.firstname("Generic")

# raises Exception: "age" must be of type: <class 'int'>
# noam.age("bla bla")

print(f"First name: {noam.firstname()}") # prints "First name: Noam"
print(f"Last name: {noam.lastname()}") # prints "Last name: Nisanov"
print(f"Full name: {noam.fullname()}") # prints "Full name: Noam Nisanov"

print(f"Current age: {noam.age()}") # prints "Current age: 22"
print(f"Birthday!") # prints "Birthday!"
noam.birthday()
print(f"New age: {noam.age()}") # prints "New age: 23"

For more information, please take a look at the project GitHub
https://github.com/nmnsnv/kisa

 

Thanks
Noam Nisanov (noam.nisanov@gmail.com)

Link to comment
Share on other sites

Link to post
Share on other sites

Cool project! You've clearly put a lot of thought and effort into it. I really like the idea making immutable variables a first-class concept, it's something I would love to see in python proper. Although as a long time pythonista and overall fan of the zen of python, I do wonder if you're trying a little too hard to make python into something it isn't. A lot of Java's features are not part of python by design, why not write your code in Java if that's the model you want?

If you haven't heard if it, you should definitely check out mypy, which uses python's optional type annotations to statically analyze your code and do type checking the same way that a language compiler does (and indeed, if your code is fully type annotated, you can compile your python with mypyc for a big performance boost). It doesn't add language features, but it does allow you to fully type check your code (including nullability, typed values cannot be None by default), and it has good IDE integration so type mismatches will show as errors in the editor.

Link to comment
Share on other sites

Link to post
Share on other sites

# raises Exception: Tried to modify a final attribute "firstname"
noam.firstname("Generic")

# raises Exception: "age" must be of type: <class 'int'>
noam.age("bla bla")

The problem I see with this: you're changing something that should be a compile time check and enforced by the compiler into a runtime check.

 

This means you can end up with a ton of hidden bugs that only get noticed once the code is running and someone calls the affected code section.

 

If you need a language that supports strong types, you should use a language that supports strong types.

 

I would expect having to add fairly verbose meta-information to classes and fields to make writing code more tedious, not less so. Also, the more verbose your code gets, the harder it'll be for a human to read and understand.

Remember to either quote or @mention others, so they are notified of your reply

Link to comment
Share on other sites

Link to post
Share on other sites

it is far better to create a transpiler that will compile a superset of python with all these bells and wistles to regular python than it is to add all these libraries and whatnots to the project. Typescript is one example of this apporach. C++ is another, a superset of C, well, most of the time anyways. some c sythnax and code behaves differently when copied and pasted into a c++ file but idea is the same. you want c but with object support baked in then use c++. 

Edited by wasab
Rewrote to clarify

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

On 1/12/2023 at 9:43 AM, NocTheRocc said:

Cool project! You've clearly put a lot of thought and effort into it. I really like the idea making immutable variables a first-class concept, it's something I would love to see in python proper. Although as a long time pythonista and overall fan of the zen of python, I do wonder if you're trying a little too hard to make python into something it isn't. A lot of Java's features are not part of python by design, why not write your code in Java if that's the model you want?

If you haven't heard if it, you should definitely check out mypy, which uses python's optional type annotations to statically analyze your code and do type checking the same way that a language compiler does (and indeed, if your code is fully type annotated, you can compile your python with mypyc for a big performance boost). It doesn't add language features, but it does allow you to fully type check your code (including nullability, typed values cannot be None by default), and it has good IDE integration so type mismatches will show as errors in the editor.

First of all, I'm glad you liked it.

As for making Python something it's not,

I think Kisa also provides features that are not presented at Java (Lombok might introduce them but could still lack default values by lambda, which I think might simplify a lot of the process (Look at https://github.com/nmnsnv/kisa#-attributes-assignment-order).

Coming from a background in Perl, I always loved the OO System provided by Moose (https://metacpan.org/pod/Moose) and I always missed it when had to deal with OOP in Python, even having default constructor with default values with nullability is something that I really miss, another thing I got to see a lot is code where variables are declared all of a sudden in some random method and it was super hard to find.

Granted, Python has dataclasses which do provide some of the functionality I get in Kisa and they do overlap a lot, I still believe Kisa is richer in it's abilities.

As for why not use Java or other language in the first place, there are many times where using a different language is not an option, for instance if you join an existing project, or want to use certain library or technology that Python supports. Also, I think Python has a lot of other very good features that justify its usage by themselves, but it's rather poor OOP makes it harder to enjoy.

As for mypy, I definitely didn't know about that library, from a quick look it does seem rather promising, I'll be sure to take a look so thanks a lot, and thank you for your response!

Edited by nmnsnv
Added thanks note ;)
Link to comment
Share on other sites

Link to post
Share on other sites

On 1/12/2023 at 3:46 PM, Eigenvektor said:
# raises Exception: Tried to modify a final attribute "firstname"
noam.firstname("Generic")

# raises Exception: "age" must be of type: <class 'int'>
noam.age("bla bla")

The problem I see with this: you're changing something that should be a compile time check and enforced by the compiler into a runtime check.

 

This means you can end up with a ton of hidden bugs that only get noticed once the code is running and someone calls the affected code section.

 

If you need a language that supports strong types, you should use a language that supports strong types.

 

I would expect having to add fairly verbose meta-information to classes and fields to make writing code more tedious, not less so. Also, the more verbose your code gets, the harder it'll be for a human to read and understand.

I do agree that compile time checks are better, but given Pythons nature I think it might be problematic to achieve (as @NocTheRocc said, mypy might be an option even though I'm not familier with it).

About the bugs that might arise, wouldn't you agree that if there is an attribute of type that isn't expected to be, it will cause those bugs sooner or later?

As I answered before, there are times when we don't have a choice about the program in use, and I tried to provide some functionality I thought is lacking in Python, and I do believe that integrating some metadata about properties in return of having a more organized code base in exchange to writing a little more code, will result in a positive outcome for future maintenance.

 

Also, I think that type checking during assignments are important as well, as there can be occasions where some "casting" to other types might occur that cannot be caught during compile time. C suffers from this issue quite a lot

 

I'd like to thank you as well for your response, it means a lot getting your feedback 🙂

Edited by nmnsnv
Added point for runtime checks
Link to comment
Share on other sites

Link to post
Share on other sites

On 1/13/2023 at 1:29 AM, wasab said:

it is far better to create a transpiler that will compile a superset of python with all these bells and wistles to regular python than it is to add all these libraries and whatnots to the project. Typescript is one example of this apporach. C++ is another, a superset of C, well, most of the time anyways. some c sythnax and code behaves differently when copied and pasted into a c++ file but idea is the same. you want c but with object support baked in then use c++. 

I do agree that a transpiler could have enhanced abilities at many places, I think that the overhead of a transpiler could be a negative side as well, as integrating a transpiler could be a lot harder then just using a Python package and using it natively, don't you think?

 

I'd like to hear your opinion about what the package brings as well as it would mean a lot to me to gain your input.

Also, thank you very much for your response.

Link to comment
Share on other sites

Link to post
Share on other sites

5 hours ago, nmnsnv said:

I do agree that a transpiler could have enhanced abilities at many places, I think that the overhead of a transpiler could be a negative side as well, as integrating a transpiler could be a lot harder then just using a Python package and using it natively, don't you think?

What is the overhead? That the python code a transpiler spits out would be bad?

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×