Here is a simple (but long) one-liner lambda
that can do what you want (partially inspired by Bakuriu).
classify = lambda module: type(module.__name__, (), {key: staticmethod(value) if callable(value) else value for key, value in ((name, getattr(module, name)) for name in dir(module))})
You might find the following function easier to read and the loops easier to see in the comprehensions.
def classify(module):
return type(module.__name__, (),
{key: staticmethod(value) if callable(value) else value
for key, value in ((name, getattr(module, name))
for name in dir(module))})
The usage is practically the same as Bakuriu's answer as you can see when talking to the interpreter.
>>> import math
>>> MathClass = classify(math)
>>> MathClass.sin(5)
-0.9589242746631385
>>> instance = MathClass()
>>> instance.sin(5)
-0.9589242746631385
>>> math.sin(5)
-0.9589242746631385
>>>
Addendum:
After realizing one of the uses of turning a module into a class, the following example program was written showing how to use the converted module as a base class. The pattern may not be recommendable for common use but does show an interesting application of the concept. The classify
function should also be easier to read in the version shown below.
import math
def main():
print(Point(1, 1) + Point.polar(45, Point.sqrt(2)))
def classify(module):
return type(module.__name__, (), {
key: staticmethod(value) if callable(value) else value
for key, value in vars(module).items()
})
class Point(classify(math)):
def __init__(self, x, y):
self.__x, self.__y = float(x), float(y)
def __str__(self):
return str((self.x, self.y))
def __add__(self, other):
return type(self)(self.x + other.x, self.y + other.y)
@property
def x(self):
return self.__x
@property
def y(self):
return self.__y
@classmethod
def polar(cls, direction, length):
radians = cls.radians(direction)
x = round(cls.sin(radians) * length, 10)
y = round(cls.cos(radians) * length, 10)
return cls(x, y)
if __name__ == '__main__':
main()