Reputation: 127
I find myself often writing attrs classes that looks something like this:
import attrs
from some_app import Client
@attrs.mutable
class Foo:
_credentials: str = attrs.field(validator=attrs.validators.instance_of(str))
_client: Client = attrs.field(
init=False,
validator=attrs.validators.instance_of(Client),
default=attrs.Factory(lambda self: Client(self._credentials), takes_self=True),
)
def bla(self):
return self._client.do_stuff
I'd like to know if there is a way to exclude the _client field from operations like deepcopying or pickling?
Thanks in advance!
Upvotes: 0
Views: 26
Reputation: 653
You can rewrite __deepcopy__()
method for your class and rebuild a new Class without properties you do not want to copy (_client
in your case, and p_hidden
in my example) by using type
.
from copy import deepcopy
class ClassA(object):
p_hidden = 1
def __init__(self, value):
self.p_shown = value
def __deepcopy__(self, memodict={}):
return type('ClassA', ClassA.__bases__, {k: v for k, v in ClassA.__dict__.items() if k != 'p_hidden'})(self.p_shown)
a = ClassA('some values')
print(a.p_shown) # 'some values'
print(a.p_hidden) # 1
b = deepcopy(a)
print(b.p_shown) # 'some values'
# print(b.p_hidden) # AttributeError: 'ClassA' object has no attribute 'p_hidden'
from pickle import dumps
c = dumps(a)
print(c) # b'\x80\x03c__main__\nClassA\nq\x00)\x81q\x01}q\x02X\x07\x00\x00\x00p_shownq\x03X\x0b\x00\x00\x00some valuesq\x04sb.'
If you just do not want your class deepcopied, just define an empty __reduce__()
method or a __deepcopy__()
method, like:
from copy import deepcopy
class ClassA(object):
p_hidden = 1
def __init__(self, value):
self.p_shown = value
def __reduce__(self): # or def __deepcopy__(self, memodict={}):
pass
Upvotes: 0