-1
In [1]: def test(array, func):
   ...:     midres = [x**2 for x in array]
   ...:     return func(midres)
   ...:

In [2]: test([1,2,3], sum)
Out[2]: 14

In [3]: p = test([2,3], sum)

Is it possible to get to the midres that was calculated when obtaining the value of p (i.e. [4,9] in this case), but without altering the test function? Of course, p.midres doesn't work; but is there a way to get it without including midres in the return statement?

I've seen this question here but it doesn't really answer my question since I'd like to get to midres through p, if possible.

Thanks in advance.

P. Prunesquallor
  • 561
  • 1
  • 10
  • 26
  • 1
    Assign it to a variable outside the function? Why not return it? – Andrew Li Feb 05 '18 at 21:52
  • @Li357 This requires a modification of `test`. – DYZ Feb 05 '18 at 21:56
  • 1
    Why do you want to do this, and why do you want to do it without modifying `test`? The reason you want to do this will determine what the best answer would be, whether it's "just modify `test` already" or "here's a quick way to redefine `test` without retyping it" or "use a `func` that gives you access to `midres`" or "check out ipdb". – user2357112 Feb 05 '18 at 21:59
  • What if you redesign `test` so it doesn't have this variable? The internal workings of a function should be transparent to the callers. – Barmar Feb 05 '18 at 22:38

2 Answers2

1

You can simply decorate your test function, thus you do not have to change anything of test. And get exactly the attribute like p.medris as you wish.

def make_wrapper(func):
    def wrapped(array, f):
        def with_attribute():
            return func(array, f)
        with_attribute.midres = func(array, lambda x:x)
        return with_attribute
    return wrapped

@make_wrapper
def test(array, func):
    midres = [x**2 for x in array]
    return func(midres)

p=test([1,2,3],sum)

# if you want only the value
print(p()) # --> 14 

# if you want midres attribute 
print(p.midres) # --> [1, 4, 9]

If you want to make it looks a bit more uniform. You can create another attribute called, for example, value. Then you do not have to run the function p() to get its value.

def make_wrapper_value(func):
    def wrapped(array, f):
        def with_attribute():
            pass
        with_attribute.value = func(array, f)
        with_attribute.midres = func(array, lambda x:x)
        return with_attribute
    return wrapped

@make_wrapper_value
def test(array, func):
    midres = [x**2 for x in array]
    return func(midres)

p=test([1,2,3],sum)

print(p.value) # --> 14 
print(p.midres) # --> [1, 4, 9]
englealuze
  • 1,445
  • 12
  • 19
0

You can instrument the function func to return its parameter in addition to whatever it calculates:

def my_sum(x):
    return sum(x), x

p, midres = test([2,3], my_sum)
#13
#[4, 9]
DYZ
  • 55,249
  • 10
  • 64
  • 93
  • Sure, but I was naively trying to see if there was a way to do it without changing the return statement. I guess another option would be to declare midres a global variable. Thanks! – P. Prunesquallor Feb 05 '18 at 22:00
  • @P.Prunesquallor that would not be a good option, and that would require you to modify the function anyway! – juanpa.arrivillaga Feb 05 '18 at 22:01
  • Note that I did not make any changes to `test`. Its `return` is exactly the same as before. – DYZ Feb 05 '18 at 22:23