3

A commonly repeated best practice is to not reuse local variables. However, when doing multiple small operations on the same variable, I struggle both with coming up with good names for all the variables, and I find that the multiple similar names hurt the readability.

Alternative 1: always create new variables

def clean_text(self, text: str) -> str:
    text_without_double_quotes = self._replace_double_quotes_with_single_quotes(text)
    text_without_double_quotes_and_foo = self._replace_foo_with_bar(text)
    text_without_double_quotes_and_foo_with_formatted_html = self._format_html(text)
    return text_without_double_quotes_and_foo_with_formatted_html

Alternative 2: reuse the variable

def clean_text(self, text: str) -> str:
    text = self._replace_double_quotes_with_single_quotes(text)
    text = self._replace_foo_with_bar(text)
    text = self._format_html(text)
    return text

Alternative 1 does have the advantage that I can set a breakpoint at the end of the method and inspect how the text was transformed in each step, but I am not sure if the tradeoff in readability is worth it or not.

3
  • 5
    Where does the advise that you can't reuse local variables come from? Do you have a link for it? Commented Jan 15, 2021 at 12:54
  • Note that if you had to follow the advice, it would be called a syntax error, not advice. Commented Jan 15, 2021 at 14:33
  • @BartvanIngenSchenau, if you google "reuse local variables" you come across a lot of stack overflow answers and blog posts such as this one: daedtech.com/please-dont-recycle-local-variables . Though I have never found an example where a variable is reused but the content is altered only very slightly, which is why I asked this question.
    – Godsmith
    Commented Jan 15, 2021 at 15:05

3 Answers 3

9

The only real rule with variable names is that it should always be obvious what they refer to. Reusing a variable name can cause issues in some situations if the reassignment fundamentally changes what the variable is representing, but in your case that isn't happening.

Compare what you wrote to what this might look if instead of applying a string to a function, you were calling a builder object:

def clean_text(self, text: str) -> str:
    return text
        ._replace_double_quotes_with_single_quotes(self)
        ._replace_foo_with_bar(self)
        ._format_html(self)

Or if python had function piping semantics

def clean_text(self, text: str) -> str:
    return text
        |> self._replace_double_quotes_with_single_quotes
        |> self._replace_foo_with_bar
        |> self._format_html

This is, semantically, the same thing.

In just about any other situation I would avoid it as there usually isn't any advantage, though avoiding the absurdly long variable names you have in Alternative 1 could be considered worthwhile. In the specific case you show where no other variable assignments happen in the entire function, there's no problem and the meaning is obvious and easy to read.

2
  • 3
    I would add that one particular case to avoid in a dynamically typed language is using the same variable with multiple different types, e.g. price = cost + markup followed by price = "€{}".format(price). As the function grows, it can become confusing which operations on price make sense at different points.
    – IMSoP
    Commented Jan 15, 2021 at 14:01
  • Wow, you're right, repeated modifications on the same variable is basically just the Builder pattern. That's really insightful, thanks.
    – Godsmith
    Commented Jan 15, 2021 at 15:17
0

Neither choice is “best practice” or not; there is very little difference. In your case the function names are very clear, so you are fine using “text” as the variable names. If it wasn’t obvious what the effect of the functions is, you would use the variable names to document it.

-1

If I find myself in this position it is usually because I have neglected a Clean Code guideline.

If the variable can be reused, do you have two functions in one? Do you have repeated code?

99% of the time you will be able to refector your code into multiple functions or a function that can be called multiple times...and achieve the same thing more readably and usually in less (or simpler) code.

On the other hand, if you are coding something that needs every ounce of performance, variable reuse saves memory allocation time ... and large combined functions saves stack operation time.

So, it depends! Clean, maintainable code versus fast code. They are often (but not necessarily always) mutually exclusive.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.