Python - function attributes or mutable defaults

Say that you have a function that should support some state and behave differently depending on this state. I know two ways to implement this when the state is fully preserved by the function:

  • Using Function Attribute
  • Using a mutable default

Using a slightly modified version of Felix Klings will answer another question , here is an example function that can be used in re.sub(), so only the third matching regular expression will be replaced:

Function attribute:

def replace(match):
    replace.c = getattr(replace, "c", 0) + 1
    return repl if replace.c == 3 else match.group(0)

Changeable default value:

def replace(match, c=[0]):
    c[0] += 1
    return repl if c[0] == 3 else match.group(0)

The first seems to me cleaner, but I saw the second more often. Which is preferable and why?

+5
4

, .

( Felix Klings answer):

def replaceNthWith(n, replacement):
    c = [0]
    def replace(match):
        c[0] += 1
        return replacement if c[0] == n else match.group(0)
    return replace

:

 # reset state (in our case count, c=0) for each string manipulation
 re.sub(pattern, replaceNthWith(n, replacement), str1)
 re.sub(pattern, replaceNthWith(n, replacement), str2)
 #or persist state between calls
 replace = replaceNthWith(n, replacement)
 re.sub(pattern, replace, str1)
 re.sub(pattern, replace, str2)

, , - (match, c = [])?

(, , python - ...)

+4

. , . : "- , ", . - , ... SO, __call__:

class StatefulReplace(object):
    def __init__(self, initial_c=0):
        self.c = initial_c
    def __call__(self, match):
        self.c += 1
        return repl if self.c == 3 else match.group(0)

init:

replace = StatefulReplace(0)
+2

:

, . , , :

class Replacer(object):
    c = 0
    @staticmethod # if you like
    def replace(match):
        replace.c += 1
        ...

, getattr. . , - , .

( , ). . -, , , , . , ( c reset ).

+1

. , . ; .

, . , , (.. ), , .

. , , . , , , , .

+1
source

All Articles