我想知道是否可以将Python类的方法保存在与类定义不同的文件中,如下所示:
main_module.py:
class Instrument(Object):
# Some import statement?
def __init__(self):
self.flag = True
def direct_method(self,arg1):
self.external_method(arg1, arg2)
to_import_from.py:
def external_method(self, arg1, arg2):
if self.flag:
#doing something
#...many more methods
就我而言,to_import_from.py
是机器生成的,包含许多方法。我宁愿不将它们复制粘贴到main_module.py或逐个导入它们,但要将它们全部识别为Instrument类的方法,就像它们已在那里定义一样:
>>> instr = Instrument()
>>> instr.direct_method(arg1)
>>> instr.external_method(arg1, arg2)
谢谢!
答案 0 :(得分:9)
人们似乎在思考这个问题。方法只是类构造范围中的函数值局部变量。所以以下工作正常:
class Instrument(Object):
# load external methods
from to_import_from import *
def __init__(self):
self.flag = True
def direct_method(self,arg1):
self.external_method(arg1, arg2)
答案 1 :(得分:7)
我认为你想要的东西在Python中是不可能的。
但是,您可以尝试以下方法之一。
to_import_from.py
时,也会在此处添加非生成的内容。这条路,
所有方法都在同一个类定义中。to_import_from.py
包含Instrument类的基类定义
继承。换句话说,在to_import_from.py
:
class InstrumentBase(object):
def external_method(self, arg1, arg2):
if self.flag:
...
然后在main_module.py
:
import to_import_from
class Instrument(to_import_from.InstrumentBase):
def __init__(self):
...
答案 2 :(得分:6)
比你想象的容易:
class Instrument(Object):
def __init__(self):
self.flag = True
def direct_method(self,arg1):
self.external_method(arg1, arg2)
import to_import_from
Instrument.external_method = to_import_from.external_method
完成!
虽然让机器生成的代码生成一个类定义并从中进行子类化将是一个更简洁的解决方案。
答案 3 :(得分:4)
您可以使用__getattr__
方法
external.py
def external_function(arg):
print("external", arg)
main.py:
import external
class Instrument(object):
def __getattr__(self, name):
if hasattr(external, name):
return getattr(external, name)
else:
return Object.__getattr__(self, name)
def direct_method(self, arg):
print("internal", arg)
i = Instrument()
i.direct_method("foo")
i.external_function("foo")
答案 4 :(得分:3)
对不起,这有点像"You shouldn't be putting nails in the wall" answer,但你忽略了python类定义。您应该将具有所有方法的类放在它自己的python文件中,并放在main_module.py
中
from instrument import Instrument
如果您打算将方法用于多个类,则应考虑进行子类化。在您的情况下,机器生成的文件可以包含Instrument
继承的基类。
最后,为您的班级提供一个很好的文档字符串,向其用户解释API,因此不需要使用“标题文件”作为您班级的概述。
答案 5 :(得分:2)
您正在做的是使用一些“机器生成的”代码扩展基类。
选择1.使用机器生成的代码扩展基类。
machine_generated.py
# Start of boilerplate #
import main_module
class Instrument_Implementation( main_module.Instrument_Abstraction ):
def direct_method(self,arg1):
# End of boilerplate #
...the real code...
然后,您的应用可import machine_generated
使用machine_generated.Instrument_Implementation
。
选择2.只需使用一流的功能。
machine_generated.py
def external_method(self, arg1, arg2):
...the real code...
main_module.py
import machine_generated
class Instrument( object ):
def direct_method(self,arg1):
return machine_generator.external_method( arg1, ... )
您的申请可以import main_module
并使用main_module.Instrument
。
答案 6 :(得分:0)
这是我的尝试。我认为使用元类可以做出更好的方法......
to_import_from.py:
def external_method(self, arg1, arg2):
if self.flag:
print "flag is set"
else :
print "flag is not set"
instrument.py:
import imp
import os
import inspect
import new
import pdb
class MethodImporter(object) :
def __init__(self, path_to_module) :
self.load_module(path_to_module)
def load_module(self, path_to_module) :
name = os.path.basename(path_to_module)
module_file = file(path_to_module,"r")
self.module = imp.load_module(name, module_file , path_to_module, ('','r',imp.PY_SOURCE))
print "Module %s imported" % self.module
for method_name, method_object in inspect.getmembers(self.module, inspect.isfunction) :
print "adding method %s to %s" % (method_name, self)
setattr(self, method_name, new.instancemethod(method_object, self, self.__class__))
class Instrument(MethodImporter):
def __init__(self):
super(Instrument,self).__init__("./to_import_from.py")
self.flag = True
def direct_method(self,arg1):
self.external_method(arg1, arg2)
运行此代码时
arg1, arg2 = 1, 2
instr = Instrument()
instr.direct_method(arg1)
instr.external_method(arg1, arg2)
这是输出:
Module <module 'to_import_from.py' from './to_import_from.pyc'> imported
adding method external_method to <__main__.Instrument object at 0x2ddeb0>
flag is set
flag is set
答案 7 :(得分:0)
从技术上讲,是的,这是可能的,但以这种方式解决它并不是真正惯用的python,并且可能有更好的解决方案。以下是如何执行此操作的示例:
import to_import_from
class Instrument(object):
locals().update(dict((k,v) for (k,v) in
to_import_from.__dict__.iteritems() if callable(v)))
def __init__(self):
self.flag = True
def direct_method(self,arg1):
self.external_method(arg1, arg2)
这将导入to_import_from
中定义的所有可调用函数作为Instrument
类的方法,以及添加更多方法。注意:如果您还想将全局变量复制为实例变量,则需要优化检查。另请注意,它会在to_import_from的命名空间中添加所有可调用对象,包括从其他模块导入(即from module import some_func
样式导入)
但是,这不是一个非常好的方法。更好的方法是将代码生成调整为生成类,并让您的类继承它。这避免了将方法不必要地复制到Instrument的命名空间中,而是使用了正常的继承。即:
class Instrument(to_import_from.BaseClass):
# Add new methods here.