Welcome, guest | Sign In | My Account | Store | Cart

When a class object is created, normally the class body is exec'ed first and then the class object is generated with that resulting namespace.

This recipe lets you flip that around, and then make the class object available to the class body during execution.

Python, 23 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
"""class_hack module"""

from functools import wraps

class Body:
    def __body__(cls):
        """Generate the class body."""
        return locals()
    
class BodyMeta(type):
    def __new__(meta, name, bases, namespace):
        body = namespace.pop("__body__", None)
        cls = type.__new__(meta, name, bases, namespace)
        if body:
            arg = body.__code__.co_varnames[:body.__code__.co_argcount][0]
            @wraps(body)
            def __body__(cls):
                return dict((k, v) for k, v in body(cls).items() if k != arg)
            for key, value in __body__(cls).items():
                setattr(cls, key, value)

            setattr(cls, "__body__", staticmethod(__body__))
        return cls

Example

class Something(metaclass=BodyMeta):
    def __body__(cls):
        "some doc"
        #class body goes here
        def __init__(self, name):
            self._name = name
        @property
        def name(self):
            return self._name
        return locals()

print(Something.__init__)
# <function __init__ at ...>
print(Something.name)
# <property object at ...>
print(Something.__body__)
# <function __body__ at ...>
print(Something("Bob").name)
# Bob