Skip to content

Instantly share code, notes, and snippets.

@Fuyukai
Created March 14, 2018 23:08
Show Gist options
  • Save Fuyukai/90c1ea8e294bfae1dd2f93dc48eca03b to your computer and use it in GitHub Desktop.
Save Fuyukai/90c1ea8e294bfae1dd2f93dc48eca03b to your computer and use it in GitHub Desktop.
Python, without classes.
def _suspend_self(namespace, suspended):
"""
Suspends a function, so that it has a self.
:param namespace: The self namespace to use.
:return: A function that will call the next function with self.
"""
def suspender(*args, **kwargs):
return suspended(namespace, *args, **kwargs)
suspender.__name__ = suspended.__name__
suspender.__defaults__ = suspended.__defaults__
suspender.__signature__ = getattr(suspended, "__signature__", None)
return suspender
def make_class(locals: dict):
"""
Makes a class, from the locals of the callee.
:param locals: The locals to build the class from.
"""
# try and find a `__call__` to implement the call function
# this is made as a function so that namespace and called can refer to eachother
def call_maker():
if '__call__' in locals and callable(locals['__call__']):
return _suspend_self(namespace, locals['__call__'])
def _not_callable(*args, **kwargs):
raise TypeError('This is not callable')
return _not_callable
# this acts as the "self" object
# all attributes are set on this
def namespace():
return called()
# get the callable function that namespace delegates to
# this is called afterwards so that call_maker has the chance to load namespace from cellvars
called = call_maker()
# make an init substitute function
def new_class(*args, **kwargs):
init = locals.get("__init__")
if init is not None:
init(namespace, *args, **kwargs)
return namespace
# update namespace
for name, item in locals.items():
if callable(item):
fn = _suspend_self(namespace, item)
setattr(namespace, name, fn)
return new_class
def make(fn):
"""
Makes a class from a function. Example usage:
.. code-block:: python
from noclasses import make_class, make
@make
def MyClass():
def __init__(self, first, second):
self.first = first
self.second = second
def add(self):
return self.first + self.second
return make_class(locals())
instance = MyClass(2, 2)
print(instance.add()) # 4
"""
return fn()
@hynekcer
Copy link

This is invalid. You assign attributes directly to the class, not to instances. Example:

instance = MyClass(2, 2)
instance2 = MyClass(3, 3)
print(instance.add())  # 6 but should be 4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment