Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeError: cannot deepcopy this pattern object

Trying to understand this error in my "Variable" class.

I was hoping to store a sre.SRE_Pattern in my "Variable" class. I just started copying the Variable class and noticed that it was causing all my Variable class instances to change. I now understand that I need to deepcopy this class, but now I run into "TypeError: cannot deepcopy this pattern object". Sure, I can store the pattern as a text string but the rest of my code already expects a compiled pattern! What would be the best way to copy my Variable class with a pattern object?

import re
from copy import deepcopy

class VariableWithRE(object):
    "general variable class"
    def __init__(self,name,regexTarget,type):
        self.name = name
        self.regexTarget = re.compile(regexTarget, re.U|re.M) 
        self.type = type 

class VariableWithoutRE(object):
    "general variable class"
    def __init__(self,name,regexTarget,type):
        self.name = name
        self.regexTarget = regexTarget
        self.type = type 

if __name__ == "__main__":

    myVariable = VariableWithoutRE("myName","myRegexSearch","myType")
    myVariableCopy = deepcopy(myVariable)

    myVariable = VariableWithRE("myName","myRegexSearch","myType")
    myVariableCopy = deepcopy(myVariable)
like image 706
Marcus Jones Avatar asked Jun 08 '11 13:06

Marcus Jones


3 Answers

deepcopy doesn't know anything about your classes and doesn't know how to copy them.

You can tell deepcopy how to copy your objects by implementing a __deepcopy__() method:

class VariableWithoutRE(object):
   # ...
   def __deepcopy__(self):
      return VariableWithoutRE(self.name, self.regexTarget, self.type)
like image 173
sth Avatar answered Oct 29 '22 11:10

sth


This can be worked around by patching copy module in pre-3.7 python:

import copy
import re 

copy._deepcopy_dispatch[type(re.compile(''))] = lambda r, _: r

o = re.compile('foo')
assert copy.deepcopy(o) == o
like image 40
Adam Sosnowski Avatar answered Oct 29 '22 12:10

Adam Sosnowski


This seems to be fixed in Python version 3.7+:

Compiled regular expression and match objects can now be copied using copy.copy() and copy.deepcopy(). (Contributed by Serhiy Storchaka in bpo-10076.)

as per: https://docs.python.org/3/whatsnew/3.7.html#re

Testing:

import re,copy

class C():
    def __init__(self):
       self.regex=re.compile('\d+')

myobj = C()    
foo = copy.deepcopy(myobj)
foo.regex == myobj.regex
# True
like image 5
Granitosaurus Avatar answered Oct 29 '22 13:10

Granitosaurus