gavenkoa
gavenkoa

Reputation: 48813

Proper idiomatic way to implement clone method in Python class?

How to idiomatically correct implement clone method in Python? See:

def clone(self):
    """
    Return a clone of this class
    """

Reason for clone - to construct identical class instance from usage point of view so internal state of copy may be changed without effecting original object.

To be concrete: constructor may initialize private fields which are primitive types or complex types:

def __init__(self, initial = None, width = DEFAULT_SIZE, height = DEFAULT_SIZE):
    self._width = width
    self._height = height
    self._matrix = ...complex code, list of list...

With primitive types - nothing hard. What to do with complex types?

If complex type is build-in like tuple, set, dict - there is copy.copy / copy.deepcopy package but I am unsure how usual it usage.

For complex types that foreign classes I don't know what to do.

(1) Are any helpers to make copy easy? Or conventions so I can relay on them?

When I copy object I see no reason to use provided constructors, because I already have known all internal contracts and able to manipulate of internal state privately?

(2) How I can instantiate object of same type without using constructor?

UPDATE I am taking Principles of Computing Coursera class and implement class that hidden by teaching stuff (for scoring reason).

They use clone in provided "interface". I am not experienced in Python classes so ask to proper way to deal in situation.

Upvotes: 5

Views: 3454

Answers (1)

ShadowRanger
ShadowRanger

Reputation: 155438

Either implement __deepcopy__ (and/or __copy__) to provide direct support to the copy module APIs, or register a pickle-ing function with copyreg; copy.deepcopy will use copyreg registered method to implement deepcopying if no __deepcopy__ is defined.

Note that many Python types (e.g. dict, list, etc.) also provide a method named copy that performs a shallow copy; it's easy to support both idioms by assigning one name to the other, e.g.:

class Foo:
    def copy(self):
        ... do stuff to make a copy ...
        return newcopy
    __copy__ = copy  # Now works with copy.copy too

Upvotes: 5

Related Questions