Skip to content

Instantly share code, notes, and snippets.

@zerotypic
Created September 9, 2021 16:03
Show Gist options
  • Select an option

  • Save zerotypic/0b060e1012b5ef2137a4ad8bdc8f0ec1 to your computer and use it in GitHub Desktop.

Select an option

Save zerotypic/0b060e1012b5ef2137a4ad8bdc8f0ec1 to your computer and use it in GitHub Desktop.
# Lazy object instantiation
class Lazy(object):
def __new__(cls, realcls, args, kwargs):
# Use the real class's __new__ to get a new object instance.
obj = realcls.__new__(realcls, *args, **kwargs)
# Replace the class with Lazy until reified.
obj.__class__ = cls
# Store info we need to reify object.
obj.__lazy_info = (realcls, args, kwargs)
return obj
#enddef
def __getattr__(self, name):
print("Getting attribute: {}".format(name))
(realcls, args, kwargs) = self.__lazy_info
self.__dict__.clear()
print("Performing class switch.")
self.__class__ = realcls
print("Calling init.")
self.__init__(*args, **kwargs)
print("Returning actual value.")
return getattr(self, name)
#enddef
def __repr__(self):
(realcls, args, kwargs) = self.__lazy_info
return "Lazy{}{}".format(realcls, (args, kwargs))
#enddef
#endclass
class LazyMeta(type):
def __call__(cls, *args, **kwargs):
return Lazy(cls, args, kwargs)
#enddef
#endclass
class Foo(object, metaclass=LazyMeta):
def __init__(self, a, b):
self.a = a
self.b = b
#enddef
def add(self): return self.a + self.b
#endclass
#############################################
# >>> f = Foo(10, 20)
# >>> type(f)
# __main__.Lazy
# >>> f.add()
# Getting attribute: add
# Performing class switch.
# Calling init.
# Returning actual value.
# 30
# >>> type(f)
# __main__.Foo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment