Last active
August 11, 2023 01:51
-
-
Save circuitsacul/669744ee86cb13fa0aa9380cf034e17c to your computer and use it in GitHub Desktop.
Strings weren't mutable, they said.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import typing as t | |
def ref(obj): | |
class Ref: | |
pass | |
slf = Ref() | |
slf.__obj = obj | |
build_methods(slf) | |
return slf | |
def build_methods(slf): | |
obj = slf.__obj | |
Ref = type(slf) | |
def make_ref_meth(orig_meth): | |
def ref_meth(*args, **kwargs): | |
if args and type(args[0]) is Ref: | |
return orig_meth(slf.__obj, *args[1:], **kwargs) | |
else: | |
return orig_meth(*args, **kwargs) | |
return ref_meth | |
def make_inplace_meth(ref_meth): | |
def inplace_meth(slf, *args, **kwargs): | |
oldtyp = type(slf.__obj) | |
slf.__obj = ref_meth(slf, *args, **kwargs) | |
if oldtyp is not type(slf.__obj): | |
build_methods(slf) | |
return slf | |
return inplace_meth | |
for k, v in vars(type(obj)).items(): | |
if k in ["__getattribute__"]: | |
continue | |
if isinstance(v, t.Callable): | |
setattr(Ref, k, ref_meth := make_ref_meth(v)) | |
if k.startswith("__") and k.endswith("__"): | |
name = k[2:-2] | |
if name.startswith("i"): | |
continue | |
inplace_name = f"__i{name}__" | |
if hasattr(type(obj), inplace_name): | |
continue | |
setattr(Ref, inplace_name, make_inplace_meth(ref_meth)) | |
else: | |
setattr(Ref, k, v) | |
return slf | |
string = ref("hello") | |
num = ref(1) | |
def double(val): | |
val += val | |
double(num) | |
double(string) | |
print(num) # 2 | |
print(string) # hellohello |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment