我有一个现有的python(python v2.7)应用程序,可以动态导入外部py文件,其中包含专门命名的类来处理数据。加载的外部py文件是根据所需数据的后处理类型选择的。
所以我有这个类的集合,每个类都在自己的文件中。根据处理类型以特定方式命名文件,以便主程序知道从上游请求导入的文件。
请记住,我和其他人总是调整这些类文件,但我们无法更改主应用程序上的代码。
我想要做的是导入一个"模板"类通用函数可以提供主程序所需的标准控件集,而无需将它们复制/粘贴到每个文件中。当我发现一个错误并在其中一个主类i / o函数中进行修正时,我讨厌它,然后我必须在其他三十个文件中进行复制。
现在,我从谷歌上了解到我的导入很糟糕......我收到了消息:
TestClassFile.py:5: SyntaxWarning: import * only allowed at module level
但是这个方法是我找到导入函数的唯一方法,因此它们进入类本身的命名空间。我在下面有一个例子......
在Python中使用哪种方法(如果有的话)?
main.py
import TestClassFile
print "New TestClass - Init"
oTest = TestClassFile.TestClass("foo")
print "Should run... Function A"
oTest.funcA()
print "Should run... Function b"
oTest.funcB()
TestClassFile.py
class TestClass:
from TestClassImport import *
def __init__(self, str):
print "INIT! and be ... ", str
def funcA(self):
print "Function A"
TestClassImport.py
def funcB(self):
print "Function B"
非常感谢!
非常感谢大家的贡献。通过研究MixIns,这些似乎是扩展类的正确python方式。
TestClassImport.py
class ImportClass:
def funcB(self):
print "Function B"
TestClassFile.py
from TestClassImport import ImportClass
class TestClass(ImportClass):
def __init__(self, str):
print "INIT! and be ... ", str
def funcA(self):
print "Function A"
答案 0 :(得分:2)
听起来你应该将导入的函数变成mixins,你可以继承它们。所以:
TestClassImport.py
class ClassB(object):
def funcB(self):
print "Function B"
TestClassFile.py
from TestClassImport import ClassB
from OtherClassImport import ClassX
class TestClass(ClassB, ClassX):
...
答案 1 :(得分:0)
我不知道这是否是一个好的解决方案,但你可以编写一个函数来构造一个元类来动态地为你的类添加属性。
def make_meta(*import_classes):
class TestMeta(type):
def __new__(meta, name, bases, dct):
new_class = super(TestMeta, meta).__new__(meta, name, bases, dct)
for import_class in import_classes:
for name in vars(import_class):
if not name.startswith('__'):
prop = getattr(import_class, name)
setattr(new_class, name, prop)
return new_class
return TestMeta
class TestClass:
import TestClassImport
__metaclass__ = make_meta(TestClassImport)
# other functions defined as normal...
这将在TestClassImport.py的全局范围内添加所有内容,而不是以“{_”作为TestClass
上的属性开头。
或者,您可以使用类装饰器以相同的方式动态添加属性。
def add_imports(*import_classes):
def augment_class(cls):
for import_class in import_classes:
for name in vars(import_class):
if not name.startswith('__'):
prop = getattr(import_class, name)
setattr(cls, name, prop)
return cls
return augment_class
import TestClassImport
@add_imports(TestClassImport)
class TestClass:
# normal class body
但mixins似乎是一种更好的方法。
答案 2 :(得分:0)
这似乎有效:
import types
from TestClassImport import funcB
class TestClass:
def __init__(self, str):
print "INIT! and be ... ", str
setattr(self, 'funcB', types.MethodType(funcB, self, TestClass))
def funcA(self):
print "Function A"
当我运行它时,我得到以下输出:
INIT! and be ... foo
Should run... Function A
Function A
Should run... Function b
Function B
答案 3 :(得分:0)
您可以使用importlib,例如:
import importlib
class TestClass:
def __init__(self, module_name):
_tmp = importlib.import_module(module_name)
for elem in _tmp.__dir__():
if not elem.startswith('_'):
prop = getattr(_tmp, elem)
setattr(self, elem, prop)
def funcA(self):
print("function A")
tc = TestClass('some_module')
tc.funcB()
>>> prints "function B"
使用这种方法,您可以创建函数load_module(module_name)
而不是__init__()
来相互独立地加载模块(例如,防止名称冲突)。