将其他文件中的函数添加到Python类
我在这个设置上遇到了问题,主要是因为我不确定我到底想要什么来解决这个问题 这是设置将其他文件中的函数添加到Python类,python,class,inheritance,Python,Class,Inheritance,我在这个设置上遇到了问题,主要是因为我不确定我到底想要什么来解决这个问题 这是设置 - main.py - lib - __init__.py - index.py - test.py \uuuu init\uuuu.py有以下代码 import os for module in os.listdir(os.path.dirname(__file__)+"/."): if module == '__init__.py' or module[-3:] != '.py':
- main.py
- lib
- __init__.py
- index.py
- test.py
\uuuu init\uuuu.py有以下代码
import os
for module in os.listdir(os.path.dirname(__file__)+"/."):
if module == '__init__.py' or module[-3:] != '.py':
continue
__import__(module[:-3], locals(), globals())
del module
class User(object):
def test(self):
return "hi"
pass
class User(object):
def tes2(self):
return "hello"
main.py现在有此代码
from lib.index import *
print User.__dict__
index.py有以下代码
import os
for module in os.listdir(os.path.dirname(__file__)+"/."):
if module == '__init__.py' or module[-3:] != '.py':
continue
__import__(module[:-3], locals(), globals())
del module
class User(object):
def test(self):
return "hi"
pass
class User(object):
def tes2(self):
return "hello"
test.py有以下代码
import os
for module in os.listdir(os.path.dirname(__file__)+"/."):
if module == '__init__.py' or module[-3:] != '.py':
continue
__import__(module[:-3], locals(), globals())
del module
class User(object):
def test(self):
return "hi"
pass
class User(object):
def tes2(self):
return "hello"
当我执行main.py
时,它成功地从index.py
打印出方法test
,但我想做的是找到一种方法,在lib文件夹中创建一个文件,而该文件在格式中只有一个函数
class User(object):
def newFunction(self):
return abc
这个函数应该在main.py中自动对我可用
我确信这不是一件困难的事情,但我真的不知道我想要什么(搜索什么来解决这个问题),这妨碍了我研究解决方案。您可以使用元类自定义类创建并添加其他地方定义的函数:
import types
import os
import os.path
import imp
class PluginMeta(type):
def __new__(cls, name, bases, dct):
modules = [imp.load_source(filename, os.path.join(dct['plugindir'], filename))
for filename in os.listdir(dct['plugindir']) if filename.endswith('.py')]
for module in modules:
for name in dir(module):
function = getattr(module, name)
if isinstance(function, types.FunctionType):
dct[function.__name__] = function
return type.__new__(cls, name, bases, dct)
class User(object):
__metaclass__ = PluginMeta
plugindir = "path/to/the/plugindir"
def foo(self):
print "foo"
user = User()
print dir(user)
然后在插件文件中,只需创建函数而不是类:
def newFunction(self, abc):
self.abc = abc
return self.abc
元类将找到它们,将它们转换为方法,并将它们附加到类中。类是对象,方法只不过是类对象上的属性 因此,如果您想将方法添加到现有类中,在原始类块之外,所有这一切都是向对象添加属性的问题,我希望您知道如何做到:
class User(object):
pass
def newFunction(self):
return 'foo'
User.newFunction = newFunction
agf的元类答案基本上是一种巧妙的自动实现方法,尽管其工作原理是在创建类之前向类块添加额外的定义,而不是在创建类之后向类对象添加额外的属性
这基本上就是开发一个框架所需的全部内容,在这个框架中,一个模块中定义的内容将自动添加到其他地方定义的类中。但您仍然需要做出一些设计决策,例如:
agf提出的元类可能是实现这种框架的一种非常好的方法,因为它允许您将所有复杂的代码放在一个地方,同时仍然“标记”每个不按类正常工作方式工作的类。不过,它确实解决了我上面提出的一些问题。这里是我们在项目中使用的工作代码,我不确定这是最好的方法,但它工作了,而且几乎没有额外的代码添加到其他文件中 cpu.py:
from cpu_base import CPU, CPUBase
import cpu_common
import cpu_ext
cpu_base.py:
def getClass():
return __cpu__
def setClass(CPUClass):
global __cpu__
__cpu__ = CPUClass
__classes__.append(CPUClass)
def CPU(*kw):
return __cpu__(*kw)
class CPUBase:
def __init__(self):
your_init_Stuff
# optionally a method classname_constructor to mimic __init__ for each one
for c in __classes__:
constructor = getattr(c, c.__name__ + '_constructor', None)
if constructor is not None:
constructor(self)
setClass(CPUBase)
cpu_common.py:
from cpu_base import getClass, setClass
class CPUCommon(getClass()):
def CPUCommon_constructor(self):
pass
setClass(CPUCommon)
cpu_ext.py:
from cpu_base import getClass, setClass
class CPUExt(getClass()):
pass
setClass(CPUExt)
使用类import CPU from CPU.py实现Ruby的开放类思想会导致一个难以调试的代码。您好,它给了我一个错误
dct[function.\uuu name\uuu]=types.MethodType(function)TypeError:调用元类基instancemethod时出错,需要至少2个参数,修复了1个
@Kartik。正确的版本是types.MethodType(function,cls)
非常感谢。代码在为目录添加函数方面起作用,但我在访问它们时遇到了问题。在这种情况下,我似乎无法在任何文件中调用self.foo()
。我得到的错误是PluginMeta没有属性foo。那不应该是User()
?@Kartik我不知道你的意思。您可以使用的唯一位置是实例方法内部--User
上的实例方法内部,或者PluginMeta
正在为您转变为实例方法的一个插件函数内部。您不能在任何其他地方调用self.foo()
,插件文件中也不应该有任何其他代码。@Kartik好的,明白了。我的错误。这又是同一行——调用MethodType
是完全错误的;我很困惑。我修复了上面的代码,但只需将该行更改为dct[function.\uuuu name\uuuu]=function
,您就可以了。