Mutating / in-place function invokation or adaptation in Python
Asked Answered
S

2

6

I often have statements in my code that do the following:

long_descriptive_variable_name = some_function(long_descriptive_variable_name)

which is very clear, but verbose and somewhat redundant at the same time. Is there any way in Python to simplify this statement perhaps by making some_function act as a "mutating" ("in-place") function?

For example, in Julia one can often do the following:

some_function!(long_descriptive_variable_name)

and this is dispatched to the version of some_function that writes directly to long_descriptive_variable_name, effectively updating the variable.

Is there any way to concisely express the same in Python for a generic function some_function ?

What about doing the same with a general object method? i.e. simplifiying

long_variable_name = long_variable_name.method(arg1, arg2)

If the above is not (easily) doable with current versions of Python, are there any PEPs considering this change in the near future?

Stlaurent answered 8/7, 2015 at 14:43 Comment(1)
I don't think that there was a direct way for such tasks, but you can create a global variable inside your function and assign the return result to that.Spot
N
1

What you're asking for can be achieved like so but I certainly wouldn't recommend doing it:

>>> x = 10
>>> def foo(func, string_of_var):
    globals()[string_of_var] = func(globals()[string_of_var])

>>> def bar(x):
    return x * 2

>>> foo(bar, 'x')
>>> x
20

As far as a PEP for changing it if there is one I doubt it would get approved. Calling a function like this that implicitly changes a value goes against the Zen of Python:

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.  <==== Relevant line
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.  <==== also probably relevant
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.  <==== And this one for good measure
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

This also would likely entail a fair amount of work without adding much to the language. Python doesn't have a ++/-- for this reason. It would have been more work to add it when x += 1 achieves the same thing. The same is true here, it would take a non trivial amount of work by several people to save you a few key strokes when calling functions.

Neumeyer answered 8/7, 2015 at 15:11 Comment(0)
E
0

DISCLAIMER: this shouldn't be used in any serious code, I wrote it just for fun and don't even think it's smart.

Not sure if this is what you wanted (so forgive me if it's off-topic), but I really enjoyed myself while creating this.

class FancyThing(object):

    def __init__(self, value):

        self.value = value

    def update(self, callback):

        self.value = callback(self.value)

    def __get__(self, instance, owner):

        return instance.value

    def __set__(self, instance, value):

        instance.value = value

    def __str__(self):

        return str(self.value)

    def __add__(self, other):

        return self.value + other

If you wrap something in this class, you can update with any random callback.

def some_func(val):
    return val * 3

a = FancyThing(3.5)
print a

a.update(tester)
print a
b = a + 5
print b

Outputs:

3.5
10.5
15.5

The funny part is that you have to define lots of built-in methods to be able to use the internal value like a normal one, like I did for __add__().

Easterly answered 8/7, 2015 at 15:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.