2

I know about the problem and how to fix it. I would like to ask for help finding this problem in existing code.

In other words, I'm trying to find all locations where this trap is buried, so I can fix it.

Is there any tool that can help me?

Community
  • 1
  • 1
max
  • 49,282
  • 56
  • 208
  • 355
  • 3
    No one with any experience would ever use a list or dictionary as a default argument. You do it once. Eight hours and lots of tears later you figure it out and never do it again ;) – nate c Nov 18 '10 at 03:08
  • "I'm trying to find all locations where this trap is buried"? Who buried it? Find the programmers that made this mistake and explain the problem to them. Why can't they learn and fix their code? – S.Lott Nov 18 '10 at 12:25
  • @S.Lott: agreed, and edited title. And it is my own code from before I learned about this problem. – max Nov 18 '10 at 19:37
  • @nate c: I agree, but that raises the question as to why the language allows mutable objects as default parameters. – max Nov 18 '10 at 19:39
  • They're perfectly legal, and meaningful. It's just that the meaning is a little surprising at first. However, people use mutable default objects to build functions which memoize their results. It's a standard, well-known, intentional part of the language. It has a use case. – S.Lott Nov 18 '10 at 20:43

3 Answers3

10

Pylint has a warning for default argument values of mutable types. It's customizable, so you could get it to just do this if you wanted.

Thomas
  • 6,515
  • 1
  • 31
  • 47
  • Unfortunately I can't seem to find Pylint to work with ActiveState Python 3.1 under Windows. Anyone knows if it's available? – max Nov 18 '10 at 19:40
3

What's wrong with grep?

grep "^\s*def.*=(\[\]|\{\}|set\(\))"

This will find just about all of the usual culprits.

If you're using a instance of one of your own mutable classes as a default value, you'll have to check for that separately.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • What if the function definition is split over multiple lines? In my limited experience, I never get a regex expression to correctly search inside code. – max Nov 18 '10 at 19:44
  • @max: How many function definitions span multiple lines? How big is your code base? This is a one-time only exercise. If it requires using grep to find function definitions which are not complete on one line, that's okay. You'll never do this job again. – S.Lott Nov 18 '10 at 20:41
  • 1
    @max I know this is old, but to find the (rare) multi-line variants, this should work .. pcregrep should ship with most flavors of linux, although not on OSX and I don't know about availability for Windows: `find . -name "*py" | xargs pcregrep -M 'def .+?\([^)]+[\[{[]'` – slinkp Oct 09 '13 at 19:25
0

The regex proposed by @S.Lott is also finding function/method calls, but we just want to find function/method definitions.

So here is an updated version of the regex to find the location of all function/method signatures which uses mutable default argument:

def .+?\([^:]*?(=\[\]|=\{\}|set\(\))[^:]*?\):

Note:

if you are using PyCharm, it will add a yellowish background to these arguments and help you change the code.

Enjoy!

Pascal
  • 15,257
  • 2
  • 52
  • 65