假设我有一个带有束方法的文件,如bunch_methods.py:
def one(x):
return int(x)
def two(y)
return str(y)
有没有办法通过导入模块整体或选择方法来获取该组方法,并将导入转换为类?
e.g。伪明智
def make_class_from_module(which_module_or_listing_of_methods):
class = turn_module_to_class(which_module_or_listing_of_methods)
return class
所以
BunchClass = make_class_from_module(bunch_methods)
在我看来听起来很合理,但它有多可行?如果我应该,或者我的替代方案是什么,我将如何开始做这样的事情?
为什么我要这样做?现在它是一个精神和心理学习练习,但我的具体用途是采取方法并创建flask-classy FlaskView classes。我想潜在地采取一些方法并可能使用&使用FlaskView
在不同的上下文中重用它们答案 0 :(得分:1)
不知道你为什么要这样做,但一个简单的方法可能是:
def to_class(module):
class TheClass(object): pass
for attr in dir(module):
val = getattr(module, attr)
if callable(val):
setattr(TheClass, attr, staticmethod(val))
return TheClass
用法:
>>> import math
>>> Math = to_class(math)
>>> m = Math()
>>> m.sin(5)
-0.9589242746631385
>>> math.sin(5)
-0.9589242746631385
>>> Math.sin(5)
-0.9589242746631385
如果模块还有一些变量,你可以增强它以将不可调用的对象添加到类中:
def to_class(module):
class TheClass(object): pass
for attr in dir(module):
val = getattr(module, attr)
if callable(val):
setattr(TheClass, attr, staticmethod(val))
else:
setattr(TheClass, attr, val)
return TheClass
然而,做更多的事情变得非常困难和丑陋,你必须有一个真的这样做的理由,否则这是浪费精力。
答案 1 :(得分:1)
您也可以使用type
元类来解决此问题。使用type
生成类的格式如下:
type(name of the class,
tuple of the parent class (for inheritance, can be empty),
dictionary containing attributes names and values)
首先,我们需要重新修改你的函数,把一个类作为第一个属性。
def one(cls, x):
return int(x)
def two(cls, y):
return str(y)
将此保存为bunch_method.py,现在我们可以按如下方式构建我们的类。
>>> import bunch_methods as bm
>>> Bunch_Class = type('Bunch_Class', (), bm.__dict__)
>>> bunch_object = Bunch_Class()
>>> bunch_object.__class__
<class '__main__.Bunch_Class'>
>>> bunch_object.one(1)
1
>>> bunch_object.two(1)
'1'
有关元类的优秀(和长篇)指南,请参阅以下帖子。 What is a metaclass in Python?
答案 2 :(得分:1)
这是一个简单(但很长)的单行lambda
,它可以做你想要的(部分受到 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))})
您可能会发现以下功能更易于阅读,并且在理解中更容易看到循环。
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))})
使用与 Bakuriu的答案几乎相同,正如您在与口译员交谈时所看到的那样。
>>> import math
>>> MathClass = classify(math)
>>> MathClass.sin(5)
-0.9589242746631385
>>> instance = MathClass()
>>> instance.sin(5)
-0.9589242746631385
>>> math.sin(5)
-0.9589242746631385
>>>
<强>附录:强>
在实现将模块转换为类的一种用法之后,编写了以下示例程序,演示如何将转换后的模块用作基类。该模式可能不适合常用,但确实显示了该概念的有趣应用。在下面显示的版本中,classify
函数也应该更容易阅读。
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()
答案 3 :(得分:0)
我不知道为什么你会想要这个,因为你已经可以将模块用作一个类,但无论如何:
import bunch_methods as bm
print bm.one('1')
print bm.two(1)
class BunchClass:
def __init__(self, methods):
self.__dict__.update(methods.__dict__)
bc = BunchClass(bm)
print bc.one('2')
print bc.two(2)