Skip to content

Instantly share code, notes, and snippets.

@isidentical
Created April 13, 2019 16:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save isidentical/c68849d34b0ce53dacc6ca99108f6e1f to your computer and use it in GitHub Desktop.
Save isidentical/c68849d34b0ce53dacc6ca99108f6e1f to your computer and use it in GitHub Desktop.
import collections.abc
from itertools import chain
MUTABLE_TYPES = tuple(
filter(
lambda item: isinstance(item, type) and item.__name__.startswith("Mutable"),
collections.abc.__dict__.values(),
)
)
class ClassAttributeFactory(type):
def __prepare__(name, bases, **factory):
if bases:
mutable_attrs = chain.from_iterable(
filter(
lambda attr: not attr[0].startswith("__")
and isinstance(attr[1], MUTABLE_TYPES),
vars(base).items(),
)
for base in bases
)
return {attr: value.copy() for attr, value in mutable_attrs}
return {}
class Parent(metaclass=ClassAttributeFactory):
items = []
test = {}
class Child(Parent):
pass
Parent.items.append(1)
Child.items.append(2)
assert Parent.items == [1]
assert Child.items == [2]
assert Child.items is not Parent.items
assert Child.test is not Parent.test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment