From 636748ed9447ddb504702962c2fef58067a91a75 Mon Sep 17 00:00:00 2001 From: Object905 Date: Sun, 24 Dec 2023 12:46:54 +0500 Subject: [PATCH 1/5] perf(python): add __slots__ to pl.Expr --- py-polars/polars/api.py | 1 - py-polars/polars/expr/expr.py | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/py-polars/polars/api.py b/py-polars/polars/api.py index 97c45350d336..f1020b50bc09 100644 --- a/py-polars/polars/api.py +++ b/py-polars/polars/api.py @@ -43,7 +43,6 @@ def __get__(self, instance: NS | None, cls: type[NS]) -> NS | type[NS]: return self._ns ns_instance = self._ns(instance) # type: ignore[call-arg] - setattr(instance, self._accessor, ns_instance) return ns_instance diff --git a/py-polars/polars/expr/expr.py b/py-polars/polars/expr/expr.py index d870bc8ca528..0e038427f8db 100644 --- a/py-polars/polars/expr/expr.py +++ b/py-polars/polars/expr/expr.py @@ -109,7 +109,8 @@ class Expr: """Expressions that can be used in various contexts.""" - _pyexpr: PyExpr = None + __slots__ = ("_pyexpr",) + _pyexpr: PyExpr _accessors: ClassVar[set[str]] = { "arr", "cat", From a544e9af2e773ad8210d820e35b7596d5ba93ca1 Mon Sep 17 00:00:00 2001 From: Object905 Date: Sun, 24 Dec 2023 12:49:17 +0500 Subject: [PATCH 2/5] perf(python): add __slots__ to pl.Expr subclasses --- py-polars/polars/expr/whenthen.py | 8 ++++++++ py-polars/polars/selectors.py | 1 + 2 files changed, 9 insertions(+) diff --git a/py-polars/polars/expr/whenthen.py b/py-polars/polars/expr/whenthen.py index f357289fec46..ced5df6d68fe 100644 --- a/py-polars/polars/expr/whenthen.py +++ b/py-polars/polars/expr/whenthen.py @@ -24,6 +24,8 @@ class When: In this state, `then` must be called to continue to finish the expression. """ + __slots__ = ("_when",) + def __init__(self, when: Any): self._when = when @@ -49,6 +51,8 @@ class Then(Expr): Represents the state of the expression after `pl.when(...).then(...)` is called. """ + __slots__ = ("_then",) + def __init__(self, then: Any): self._then = then @@ -106,6 +110,8 @@ class ChainedWhen(Expr): In this state, `then` must be called to continue to finish the expression. """ + __slots__ = ("_chained_when",) + def __init__(self, chained_when: Any): self._chained_when = chained_when @@ -131,6 +137,8 @@ class ChainedThen(Expr): Represents the state of the expression after an additional `then` is called. """ + __slots__ = ("_chained_then",) + def __init__(self, chained_then: Any): self._chained_then = chained_then diff --git a/py-polars/polars/selectors.py b/py-polars/polars/selectors.py index 0793f5b9ee57..846dd4472bd6 100644 --- a/py-polars/polars/selectors.py +++ b/py-polars/polars/selectors.py @@ -242,6 +242,7 @@ def _combine_as_selector( class _selector_proxy_(Expr): """Base column selector expression/proxy.""" + __slots__ = ("_attrs", "_repr_override") _attrs: dict[str, Any] _repr_override: str From 0017966531cefe79dc7538e2afcb58e67bfdc6e1 Mon Sep 17 00:00:00 2001 From: Object905 Date: Fri, 5 Jan 2024 16:57:28 +0500 Subject: [PATCH 3/5] feat: add __slots__ to LazyFrame --- py-polars/polars/lazyframe/frame.py | 1 + 1 file changed, 1 insertion(+) diff --git a/py-polars/polars/lazyframe/frame.py b/py-polars/polars/lazyframe/frame.py index db79335f290f..7827ba8de667 100644 --- a/py-polars/polars/lazyframe/frame.py +++ b/py-polars/polars/lazyframe/frame.py @@ -286,6 +286,7 @@ class LazyFrame: └─────┴─────┴─────┘ """ + __slots__ = ("_ldf",) _ldf: PyLazyFrame _accessors: ClassVar[set[str]] = set() From 10f723ff53cbeff0135772fe82a7143295b25f80 Mon Sep 17 00:00:00 2001 From: Object905 Date: Fri, 5 Jan 2024 18:28:17 +0500 Subject: [PATCH 4/5] feat: add __slots__ to parameter-less dtype classes --- py-polars/polars/datatypes/classes.py | 59 +++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/py-polars/polars/datatypes/classes.py b/py-polars/polars/datatypes/classes.py index d9e2fde8614c..5a731267f08b 100644 --- a/py-polars/polars/datatypes/classes.py +++ b/py-polars/polars/datatypes/classes.py @@ -90,6 +90,8 @@ def is_nested(self) -> bool: # noqa: D102 class DataType(metaclass=DataTypeClass): """Base class for all Polars data types.""" + __slots__ = () + def __reduce__(self) -> Any: return (_custom_reconstruct, (type(self), object, None), self.__dict__) @@ -267,70 +269,104 @@ def __contains__(self, item: Any) -> bool: class NumericType(DataType): """Base class for numeric data types.""" + __slots__ = () + class IntegerType(NumericType): """Base class for integer data types.""" + __slots__ = () + class SignedIntegerType(IntegerType): """Base class for signed integer data types.""" + __slots__ = () + class UnsignedIntegerType(IntegerType): """Base class for unsigned integer data types.""" + __slots__ = () + class FloatType(NumericType): """Base class for float data types.""" + __slots__ = () + class TemporalType(DataType): """Base class for temporal data types.""" + __slots__ = () + class NestedType(DataType): """Base class for nested data types.""" + __slots__ = () + class Int8(SignedIntegerType): """8-bit signed integer type.""" + __slots__ = () + class Int16(SignedIntegerType): """16-bit signed integer type.""" + __slots__ = () + class Int32(SignedIntegerType): """32-bit signed integer type.""" + __slots__ = () + class Int64(SignedIntegerType): """64-bit signed integer type.""" + __slots__ = () + class UInt8(UnsignedIntegerType): """8-bit unsigned integer type.""" + __slots__ = () + class UInt16(UnsignedIntegerType): """16-bit unsigned integer type.""" + __slots__ = () + class UInt32(UnsignedIntegerType): """32-bit unsigned integer type.""" + __slots__ = () + class UInt64(UnsignedIntegerType): """64-bit unsigned integer type.""" + __slots__ = () + class Float32(FloatType): """32-bit floating point type.""" + __slots__ = () + class Float64(FloatType): """64-bit floating point type.""" + __slots__ = () + class Decimal(NumericType): """ @@ -342,6 +378,8 @@ class Decimal(NumericType): It may be changed at any point without it being considered a breaking change. """ + __slots__ = ("precision", "scale") + precision: int | None scale: int @@ -383,10 +421,14 @@ def __hash__(self) -> int: class Boolean(DataType): """Boolean type.""" + __slots__ = () + class String(DataType): """UTF-8 encoded string type.""" + __slots__ = () + # Allow Utf8 as an alias for String Utf8 = String @@ -395,14 +437,20 @@ class String(DataType): class Binary(DataType): """Binary type.""" + __slots__ = () + class Date(TemporalType): """Calendar date type.""" + __slots__ = () + class Time(TemporalType): """Time of day type.""" + __slots__ = () + class Datetime(TemporalType): """Calendar date and time type.""" @@ -606,14 +654,20 @@ def __repr__(self) -> str: class Object(DataType): """Type for wrapping arbitrary Python objects.""" + __slots__ = () + class Null(DataType): """Type representing Null / None values.""" + __slots__ = () + class Unknown(DataType): """Type representing Datatype values that could not be determined statically.""" + __slots__ = () + class List(NestedType): """Variable length list type.""" @@ -738,6 +792,10 @@ def __repr__(self) -> str: class Field: """Definition of a single field within a `Struct` DataType.""" + __slots__ = ("name", "dtype") + name: str + dtype: PolarsDataType + def __init__(self, name: str, dtype: PolarsDataType): """ Definition of a single field within a `Struct` DataType. @@ -766,6 +824,7 @@ def __repr__(self) -> str: class Struct(NestedType): """Struct composite type.""" + __slots__ = ("fields",) fields: list[Field] def __init__(self, fields: Sequence[Field] | SchemaDict): From 7da83bddaf85c3d02f72f360848f90e0a39ba05f Mon Sep 17 00:00:00 2001 From: Object905 Date: Sat, 17 Feb 2024 13:03:11 +0500 Subject: [PATCH 5/5] feat: add __slots__ to Series, DataFrame, Categorical and Enum --- py-polars/polars/dataframe/frame.py | 2 ++ py-polars/polars/datatypes/classes.py | 4 +++- py-polars/polars/series/series.py | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/py-polars/polars/dataframe/frame.py b/py-polars/polars/dataframe/frame.py index 85337cf64d1d..dfe346d27710 100644 --- a/py-polars/polars/dataframe/frame.py +++ b/py-polars/polars/dataframe/frame.py @@ -347,6 +347,8 @@ class DataFrame: False """ + __slots__ = ("_df",) + _df: PyDataFrame _accessors: ClassVar[set[str]] = {"plot"} def __init__( diff --git a/py-polars/polars/datatypes/classes.py b/py-polars/polars/datatypes/classes.py index 5a731267f08b..9c22af7f0ad2 100644 --- a/py-polars/polars/datatypes/classes.py +++ b/py-polars/polars/datatypes/classes.py @@ -237,6 +237,7 @@ def _custom_reconstruct( class DataTypeGroup(frozenset): # type: ignore[type-arg] """Group of data types.""" + __slots__ = ("_match_base_type",) _match_base_type: bool def __new__( @@ -379,7 +380,6 @@ class Decimal(NumericType): """ __slots__ = ("precision", "scale") - precision: int | None scale: int @@ -558,6 +558,7 @@ class Categorical(DataType): or string value (lexical). """ + __slots__ = ("ordering",) ordering: CategoricalOrdering | None def __init__( @@ -592,6 +593,7 @@ class Enum(DataType): It may be changed at any point without it being considered a breaking change. """ + __slots__ = ("categories",) categories: Series def __init__(self, categories: Series | Iterable[str]): diff --git a/py-polars/polars/series/series.py b/py-polars/polars/series/series.py index 50c65d252255..4f6ba67f94ae 100644 --- a/py-polars/polars/series/series.py +++ b/py-polars/polars/series/series.py @@ -237,7 +237,8 @@ class Series: ] """ - _s: PySeries = None + __slots__ = ("_s",) + _s: PySeries _accessors: ClassVar[set[str]] = { "arr", "cat",