Не возвращать мутированный объект - это Pythonism, который напоминает вам о том факте, что новый объект не был создан. По этой причине практически все стандартные библиотечные функции, которые выполняют внутреннюю мутацию, возвращают None
.
Вы можете написать свою собственную оболочку (а с некоторыми getattr
magi c, сделать ее автоматизированной c) , но это, вероятно, не совсем стоит.
РЕДАКТИРОВАТЬ: Если вам нужно это только для цепочки, вы могли бы сделать что-то вроде
def chain(a, f):
f(a)
return a
x = chain(
np.random.randint(0,10+1,50),
lambda m: m.sort(),
)[:5]
или даже более причудливый,
def hyperchain(val, *fs):
for f in fs:
res = f(val)
if res is not None:
val = res
return val
, чтобы позволить вам связывать вещи, возвращающие значение, и вещи, не возвращающие:
x = hyperchain(
np.random.randint(0,10+1,50),
lambda m: m.sort(),
lambda m: m[:5],
)
РЕДАКТИРОВАТЬ 2: Вот вышеупомянутая getattr
идея обертки - не говоря, что это хорошая идея или идеальная, но здесь мы go:
from functools import wraps
class ChainWrapper:
def __init__(self, target):
self._target = target
def __getattr__(self, key):
attr = getattr(self._target, key)
if callable(attr):
@wraps(attr)
def wrapped_func(*args, **kwargs):
retval = attr(*args, **kwargs)
if retval is None:
retval = self
return retval
return wrapped_func
return attr
def __str__(self):
return self._target.__str__()
def __repr__(self):
return f"<chain-wrapped {self._target!r}"
def unwrap(self):
return self._target
# TODO: implement other things such as __getitem__ and __setitem__
# to just proxy through
l = [1, 2, 4, 8]
lw = ChainWrapper(l)
print(lw.append(8).append(10).insert(0, "hello").reverse())
Это выводит
[10, 8, 8, 4, 2, 1, 'hello']