10

The answer equals the definition of side effects.

Up to now, I don't find out a precise answer. The python doc says: Functional style discourages functions with side effects that modify internal state or make other changes that aren’t visible in the function’s return value.

What is modify internal state and make other changes that aren’t visible...?

Is binding varibles to objects(just binding, not modifying) means no side effects? e.g.a=1 or a=[1,2,3] or a,b=1,2.

Here are 4 functions. Are they all with no side effects? why?

Note, assuming the argument n must be an int object.

def purefunc1(n):
    def getn(n):
        return [1,2,3,4,5][:n-1],[1,2,3,4,5][:n]
    def addn(fir,sec,thd):
        return fir+sec+thd
    return addn(getn(n)[0],['HEY'],getn(n)[1])

def purefunc2(n):
    def getn(n):
        #bind
        arr=[1,2,3,4,5]
        return arr[:n-1],arr[:n]
    def addn(fir=[],sec=[],thd=[]):
        return fir+sec+thd
    #bind
    arg1,arg3=getn(n)
    return addn(arg1,['HEY'],arg3)

def purefunc3(n):
    arr=[1,2,3,4,5]
    def getn(n):
        #closure 'arr'
        return arr[:n-1],arr[:n]
    def addn(fir=[],sec=[],thd=[]):
        return fir+sec+thd
    #bind
    arg1,arg3=getn(n)
    return addn(arg1,['HEY'],arg3)

def purefunc4(n):
    def arr():
        return [1,2,3,4,5]
    def getn(n):
        #closure
        return arr()[:n-1],arr()[:n]
    def addn(fir=[],sec=[],thd=[]):
        return fir+sec+thd
    #bind
    arg1,arg3=getn(n)
    return addn(arg1,['HEY'],arg3)

print (purefunc1(3))
print (purefunc2(3))
print (purefunc3(3))
print (purefunc4(3))

My guess:purefunc1 is with no side effects.But I don't know the following purefunc*.

the output is:

[1, 2, 'HEY', 1, 2, 3]
[1, 2, 'HEY', 1, 2, 3]
[1, 2, 'HEY', 1, 2, 3]
[1, 2, 'HEY', 1, 2, 3]    

If you ask why exists such odd functions, the answer is it's just for convenience. The real function is complicated. but if you are interested, you can click here to see whether the function ieval is with no side effects or not.

Thank you all guys in advance.

tcpiper
  • 2,456
  • 2
  • 28
  • 41
  • 1
    From wiki page on side effects: "In the presence of side effects, a program's behavior depends on history; that is, the order of evaluation matters. Understanding and debugging a function with side effects requires knowledge about the context and its possible histories. or from programmers: http://programmers.stackexchange.com/questions/40297/what-is-a-side-effect " – dm03514 Nov 17 '13 at 04:16

4 Answers4

7

In the context of functional programming, a function is a deterministic thing that, given a input, outputs something. That's what pure functions do. They only calculate things. They dont "do" things. If your function code could theoretically be switched by a table (even an infinite one), then you have a function with no side effects.

Anything besides returning a value it's a side effect. The terms "modify internal state" and "make other changes that aren’t visible" refers to that. Modifying internal state or making changes... can means:

  1. Printing something
  2. Modifying a out of scope object
  3. Saving something

You can understand side effect as "modifying the outside world". In your examples, none of them does that. But, if you assigned something to n, like appending something, or anything that would persist in your enviroment after the function returns, then that would be a side effect.

All your functions can be tested comparing inputs and outputs. If you had side effects (like mutating n) your testing would get more complicated, and you would need to analyze the context your function is.

Lucas Ribeiro
  • 6,132
  • 2
  • 25
  • 28
5

In Python's documentation about functional programming, there's a small paragraph. I will quote below (emphasis mine):

Python programs written in functional style usually won’t go to the extreme of avoiding all I/O or all assignments; instead, they’ll provide a functional-appearing interface but will use non-functional features internally. For example, the implementation of a function will still use assignments to local variables, but won’t modify global variables or have other side effects.

In other words, think from what looks from outside. Is the function modifying some global variable, class variable? Does it manipulate any state whatsoever? If no, then its pure. According to the above docs, internally a function can assign to local variables but what is important is the function should not modify any external facing state.


What is modify internal state and make other changes that aren’t visible...?

Look at an example below. We are modifying a global_list everytime we invoke non_pure_add1_func(..).

global_list = []

def non_pure_add1_func(x):
    global_list.append(x)
    return x+1

Although, the above function might be idempotent, but its not pure.

UltraInstinct
  • 43,308
  • 12
  • 81
  • 104
3

A Python function doesn't have side-effects if and only if it doesn't modify global variables, only calls side-effect free functions, and doesn't raise exceptions which are caught. Quoting Wikipedia:

In computer science, a function or expression is said to have a side effect if, in addition to returning a value, it also modifies some state or has an observable interaction with calling functions of the outside world.

Basically a side-effect free function can be called and nothing is different after the call, i.e. everything is the same after the call.

Community
  • 1
  • 1
Ramchandra Apte
  • 4,033
  • 2
  • 24
  • 44
  • I am far from convinced that the linked answer applies: exceptions in Python are typically not treated as `bottom` -- `_|_` -- in the manner the other answer describes. – Matt Fenwick Nov 19 '13 at 12:42
3

You answered yourself. You want examples of side-effects?

def side1():
  print 'Hello!'

This modifies sys.stdout by writing to it. sys.stdout is not internal to the function.

a = 1

def side2():
  global a
  a += 2

This modifies a, a global, not local to the function.

An elegant example for storing state in a simple function (no class, nothing external) is this:

def side3(state=[]):
  # call it without arguments to make the point: side3()
  state.append(len(state))
  return state  # not returning anything still changes state...

The array (because it’s created only once at function definition) is the same for each call of the function, it’s part of it. And it modifies for each call, changing the return value depending on it’s state. :-)

Your functions don’t do any of this. That’s why they have no side-effects.

Robert Siemer
  • 32,405
  • 11
  • 84
  • 94