I'm trying to implement a lazy property. Say, an object is initialize by object._x = None
, and then I want to write something
@property
def x(self):
return self._x or (init_x_value(); x)
so that the initializer is called only the first time the attribute is looked up.
In scala, an expression can contain statements. Is something similar possible in python. If not, is there any alternative way to implement it, or should I stick with if-else
?
@NirajRaut As an example, in the assignment statement a = 42 the right-hand side 42 is an expression, but it's not an expression statement. Any expression could be used as a statement, but not every expression is actually used as a statement.
In short – An Expression always evaluates to a value. And, A statement does something, like creating a variable or displaying a value, it only does whatever the statement says.
An expression can be defined as any element in our utility that evaluates some values. An expression evaluates a value. A declaration does something. Statements represent a motion or command e.g print statements, mission statements.
In programming language terminology, an “expression” is a combination of values and functions that are combined and interpreted by the compiler to create a new value, as opposed to a “statement” which is just a standalone unit of execution and doesn't return anything.
If init_x_value
returns None
, you can simply use:
return self._x or init_x_value() or self._x
Note however, like @3Doubloons says in their comment, that if self._x
is something false-ish like None
, []
(an empty list), ()
an empty tuple, or a class which has overridden the __bool__
method, it will move on to the init method wich can be computationally expensive.
In case init_x_value
returns the calculated x
value itself, you can even write it like:
return self._x or init_x_value()
This is because the or
in Python is rather special: the x or y
works like:
if bool(x):
return x
else:
return y
and x
and y
are generated lazily. Since bool(None)
is False
in the first case, it will thus check self._x
. If self._x
is None
, it will proceed by calling init_x_value()
since that method does not return anything it implicitly returns None
which is not accepted by the or
-chain either, so it finally resolves to the last self._x
which is now set.
To answer the title question itself : no, in Python an expression can not contain a statement. period.
The proper pythonic way to write your getter is:
@property
def x(self):
# assume _x defaults to None
if self._x is None:
# here you can have has many statements as
# you like ;)
self._x = init_x_value()
return self._x
might not look as smart as triple 'or' or inline statements or whatever but it's as simple, straightforward, clear and readable as it can be.
You can hide the statements in a function:
@property
def x(self):
def initialize_and_return_x():
init_x_value()
return self._x
return self._x or initialize_and_return_x()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With