Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Python "magic" methods - part 1

Posted on Oct 19 • Originally published at blog.frankel.ch Java was the first language I used professionally and is the scale by which I measure other languages I learned afterward. It's an OOP statically-typed language. Hence, Python feels a bit weird because of its dynamic typing approach.For example, Object offers methods equals(), hashCode(), and toString(). Because all other classes inherit from Object, directly or indirectly, all objects have these methods by definition.Conversely, Python was not initially built on OOP principles and is dynamically typed. Yet, any language needs cross-cutting features on unrelated objects. In Python, these are specially-named methods: methods that the runtime interprets in a certain way but that you need to know about. You can call them magic methods.The documentation is pretty exhaustive, but it needs examples for beginners. The goal of this post is to list most of these methods and provide these examples so that I can remember them. I've divided it into two parts to make it more digestible.Methods in this section are related to the lifecycle of new objects.The __new()__ method is static, though it doesn't need to be explicitly marked as such. The method must return a new object instance of type cls; then, the runtime will call the __init__() (see below) method on the new instance.__new__() is meant to customize instance creation of subclasses of immutable classes.__init__() is the regular initialization method, which you probably know if you've read any basic Python tutorial. The most significant difference with Java is that the superclass __init__() method has no implicit calling. One can only wonder how many bugs were introduced because somebody forgot to call the superclass method.__init__() differs from a constructor in that the object is already created.If __init()__ is akin to an initializer, then __del__() is it's finalizer. As in Java, finalizers are unreliable, e.g., there's no guarantee that the interpreter finalizes instances when it shuts down.Python offers two main ways to represent objects: one "official" for debugging purposes and the other "informal". You can use the former to reconstruct the object.The official representation is expressed via the object.__repr__(self). The documentation states that the representation must be "information-rich and unambiguous".My implementation returns a string, though it's not required. Yet, you can reconstruct the object with the information displayed.The object.__str__(self) handles the unofficial representation. As its name implies, it must return a string. The default calls __repr__().Aside from the two methods above, the object.__format__(self, format_spec) method returns a string representation of the object. The second argument follows the rules of the Format Specification Mini-Language. Note that the method must return a string. It's a bit involved, so that I won't implement it.Finally, the object.__bytes__(self) returns a byte representation of the object.Let's start with similarities with Java: Python has two methods object.__eq__(self, other) and object.__hash__(self) that work in the same way. If you define __eq__() for a class, you must define __hash__() as well. Contrary to Java, if you don't define the former, you must not define the latter.As in Java, __eq__()__ and __hash__() have plenty of gotchas. Some of them are the same, others not. I won't paraphrase the documentation; have a look at it.Other comparison methods are pretty self-explanatory:Note that comparison methods may return something other than a boolean. In this case, Python will transform the value in a boolean using the bool() function. I advise you not to use this implicit conversion.As seen above, Python allows accessing an object's attributes via the dot notation. If the attribute doesn't exist, Python complains: 'Foo' object has no attribute 'a'. However, it's possible to define synthetic accessors on a class, via the object.__getattr__(self, name) and object.__setattr__(self, name, value) methods. The rule is that they are fallbacks: if the attribute doesn't exist, Python calls the method.For added fun, Python also offers the object.__getattribute__(self, name). The difference is that it's called whether the attribute exists or not, effectively shadowing it.The dir() function allows returning an object's list of attributes and methods. You can set the list using the object.__dir__(self)__ method. By default, the list is empty: you need to set it explicitly. Note that it's the developer's responsibility to ensure the list contains actual class members.Python descriptors are accessors delegates, akin to Kotlin's delegated properties. The idea is to factor a behavior somewhere so other classes can reuse it. In this way, they are the direct consequence of favoring composition over inheritance. They are available for getters, setters, and finalizers, respectively:Let's implement a lazy descriptor that caches the result of a compute-intensive operation.This concludes the first part of Python magic methods. The second part will focus on class, container, and number-related methods.Originally published at A Java Geek on October 15th, 2023Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well Confirm For further actions, you may consider blocking this person and/or reporting abuse Mike Young - Sep 27 Michael_Maranan - Sep 28 Bry - Oct 9 Vincent A. Cicirello - Sep 8 Once suspended, nfrankel will not be able to comment or publish posts until their suspension is removed. Once unsuspended, nfrankel will be able to comment and publish posts again. Once unpublished, all posts by nfrankel will become hidden and only accessible to themselves. If nfrankel is not suspended, they can still re-publish their posts from their dashboard. Note: Once unpublished, this post will become invisible to the public and only accessible to Nicolas Frankel. They can still re-publish the post if they are not suspended. Thanks for keeping DEV Community safe. Here is what you can do to flag nfrankel: nfrankel consistently posts content that violates DEV Community's code of conduct because it is harassing, offensive or spammy. Unflagging nfrankel will restore default visibility to their posts. DEV Community — A constructive and inclusive social network for software developers. With you every step of your journey. Built on Forem — the open source software that powers DEV and other inclusive communities.Made with love and Ruby on Rails. DEV Community © 2016 - 2023. We're a place where coders share, stay up-to-date and grow their careers.



This post first appeared on VedVyas Articles, please read the originial post: here

Share the post

Python "magic" methods - part 1

×

Subscribe to Vedvyas Articles

Get updates delivered right to your inbox!

Thank you for your subscription

×