Components¶
Msort formats python classes by re-ordering the components of classes into a pre-defined order.
The first level of ordering depends on the type of component.
The second level of ordering depends on the name of the component.
Fixed components¶
There are currently four types of fixed components which cannot be manually overridden by the user.
Ellipsis¶
The ellipsis has multiple uses in python but for msort it can appear as a component when used as a placeholder for a class which has not been implemented yet or during multi-inheritance patterns.
class NotImplementedClass:
...
class ConcreteClass(ParentClassOne, ParentClassTwo):
...
The ellipsis has the highest sorting level in msort, ensuring that such classes do not get reformatted.
Class docstrings¶
Class docstrings are defined by the triple quote blocks immediately beneath the class definition.
Class docstrings have a fixed high order value to ensure that they are not reformatted.
class ExampleClass:
"""
This class is an example python class used in the msort documentation.
"""
...
Typed class attributes¶
Class attributes are data defined outside of a class method and are shared across all instances of the class.
class ExampleClass:
"""
This class is an example python class used in the msort documentation.
"""
name: str = "example"
In this example, the class attribute name is defined outside of any methods and is type annotated as a string.
Therefore, msort considers name to be a typed class attribute.
Typed class attributes have a higher sorting level than untyped class attributes.
Untyped class attributes¶
class ExampleClass:
"""
This class is an example python class used in the msort documentation.
"""
age = 50
In this example, the class attribute age is defined outside of any methods and is not type annotated.
Therefore, msort considers age to be an untyped class attribute.
If we have both typed and untyped class attributes then they will be re-ordered according to whether they are typed or not and then alphabetically.
For example, this ExampleClass:
class ExampleClass:
"""
This class is an example python class used in the msort documentation.
"""
age = 50
name: str = "Joe"
pets: List[str] = ["dog", "cat"]
last_name = "Bloggs"
would be converted to:
class ExampleClass:
"""
This class is an example python class used in the msort documentation.
"""
pets: List[str] = ["dog", "cat"]
name: str = "Joe"
age = 50
last_name = "Bloggs"
Methods¶
Dunder methods¶
Dunder methods, also known as magic methods or special methods, are a set of predefined methods in Python that you can override to change the behavior of objects.
These methods allow objects to implement or emulate the behavior of built-in types and functions.
class ExampleClass:
"""
This class is an example python class used in the msort documentation.
"""
def __init__(self, name: str) -> None
self.name: str = name
self.pets: List[str] = []
def __len__(self) -> int:
return len(self.pets)
In this example, two dunder methods are defined. By default, dunder methods are awarded the highest method sorting level, ensuring that dunder methods always appear at the top of the class.
Classmethods¶
Class methods are methods that are bound to the class itself rather than to instances of the class.
They can be called on the class itself or on instances, and they have access to the class as their first argument, which is conventionally named cls. This allows them to access and modify class state that applies across all instances of the class.
Class methods are defined using the @classmethod decorator.
class ExampleClass:
"""
This class is an example python class used in the msort documentation.
"""
name: str = "example"
@classmethod
def print_name(cls) -> None
print(cls.name)
Staticmethods¶
Static methods in Python are methods that belong to a class but do not access any instance or class-specific data.
They are defined using the @staticmethod decorator. Static methods are similar to regular functions but are included in the class’s namespace, making them accessible via the class name or instances of the class.
Static methods are often used for utility functions which are strongly tied to the overall class purpose.
class MathOperations:
@staticmethod
def add(a, b):
return a + b
@staticmethod
def subtract(a, b):
return a - b
Properties¶
In Python, the @property decorator is used to define methods in a class that act like attributes. These methods are typically used for managing the access to private attributes.
The @property decorator turns a method into a “getter” for a read-only attribute.
class ExampleClass:
"""
This class is an example python class used in the msort documentation.
"""
def __init__(self, name: str) -> None
self._name: str = name
@property
def name(self) -> str:
return self._name
example = ExampleClass(name="Steve")
print(example.name) # here _name is accessed using the name property
Getters¶
The @property decorator is a pythonic way of creating a class property from scratch. The getter decorator
essentially does the same thing but using the <property>.getter syntax where <property> is the name of the
private attribute to access.
In general, the @property decorator is preferred when defining a property from scratch but the getter decorator
can be used when a subclass is modifying a property defined in a parent class.
class ExampleClass:
"""
This class is an example python class used in the msort documentation.
"""
def __init__(self, name: str) -> None
self._name: str = name
@name.getter
def name(self) -> str:
return self._name
Setters¶
Setters work in conjunction with @property and getter to support controlled access to private attributes.
The setter decorator allows controlled access whilst setting a new value.
class ExampleClass:
"""
This class is an example python class used in the msort documentation.
"""
def __init__(self, name: str) -> None
self._name: str = name
@name.getter
def name(self) -> str:
return self._name
@name.setter
def name(self, new_name: str) -> None:
self._name = name
Deleters¶
Deleters work in conjunction with getter and setter to support controlled access to private attributes.
The deleter decorator allows controlled access to remove an attribute from a class - meaning the attribute is
no longer accessible for the particular instance of the class.
class ExampleClass:
"""
This class is an example python class used in the msort documentation.
"""
def __init__(self, name: str) -> None
self._name: str = name
@name.getter
def name(self) -> str:
return self._name
@name.setter
def name(self, new_name: str) -> None:
self._name = name
@name.deleter
def name(self) -> None:
del self._name
Other decorated methods¶
Any decorated class method without any of the above mentioned decorators is considered by msort to be a
decorated method. This includes decorators such as abstractmethod, functools.lru_cache, singledispatch.
Instance methods¶
Instance methods are method which have access to the self object of an instantiated class and can access and modify
instance attributes.
Instance methods are the standard python class method.
class ExampleClass:
"""
This class is an example python class used in the msort documentation.
"""
def __init__(self, name: str) -> None
self.name: str = name
self.pets: List[str] = []
def lower_name(self) -> str:
return self.name.lower()
def add_pet(self, new_pet: str) -> None:
self.pets.append(new_pet)
lower_name() and add_pet() are instance methods.
Private methods¶
Private methods are often designated by starting with a single underscore _private_method().
Private methods are not supposed to be called outside of the class but are used by other methods of the class.
class ExampleClass:
"""
This class is an example python class used in the msort documentation.
"""
def __init__(self, first_name: str, last_name: str) -> None:
self.first_name: str = first_name
self.last_name: str = last_name
self.pets: List[str] = []
def full_name(self) -> str:
return self._lower_first_name() + " " + self._lower_second_name()
def _lower_first_name(self) -> str:
return self.first_name.lower()
def _lower_second_name(self) -> str:
return self.second_name.lower()
In this example, _lower_first_name() and _lower_second_name() are private methods. By default, msort puts
private methods at the bottom of the class.
Inner Classes¶
Classes may be defined within a class to encapsulate an inner class.
By default, msort sorts inner classes to the bottom of the class.
class ExampleClass:
"""
This class is an example python class used in the msort documentation.
"""
def __init__(self, first_name: str, last_name: str) -> None:
self.first_name: str = FirstName(first_name)
self.last_name: str = SecondName(last_name)
self.pets: List[str] = []
class FirstName:
def __init__(self, first_name: str) -> None:
self.name = first_name
class SecondName:
def __init__(self, second_name: str) -> None:
self.name = second_name
Conflicts¶
If two different components are given the same sorting level then they will be sorted alphabetically.
If the sorting level for a method is set to have higher precedence than a fixed component, then a
ValueErrorwill be raised.The
ValueErrorcan be overridden by using the--forceoption.