从子模块访问父对象

时间:2015-09-04 21:37:49

标签: python python-2.7

我正在编写一个模块,用于从本地SQLite数据库访问某些数据,并希望最终用户功能能够像这样工作:

import pyMyDB
myDBobj = pyMyDB.MyDB( '/path/to/DB/file' )  # Instance of the class MyDB

用户只需创建一个连接数据库的对象 然后,根据需要,我希望用户可以访问不同的子模块来处理来自数据库的数据。例如,Driving提供某些功能,Walking提供其他功能,我喜欢这样访问:

result = myDBobj.Driving.GetTachometerReading()

result = myDBobj.Walking.GetShoeType()

我的问题关于如何制作子模块Driving& Walking可以访问父 Object (不仅仅是Parent模块的类/函数,而是实例化的对象)。

如果我让我的文件heirarchy像这样:

pyMyDB/
    __init__.py      # imports the below modules as so:
    MyDB_class.py    # imported as *, contains MyDB class definition
    Driving.py       # imported normally via `import Driving`
    Walking.py       # imported normally

其中__init__.py导入MyDB_class.py(包含数据库类)并导入Driving/Walking.py,然后 用户可以执行pyMyDB.Driving.some_func(),但some_func()实际上无法访问实例化的MyDB对象,对吗?

有没有人遇到让子模块访问实例化对象的方法?

这是我目前的解决方案。这似乎太复杂了。

首先,我必须使用额外的globals.py文件来克服循环模块导入(Like this hint)。

Driving模块中,我创建了一个名为Drv的新类,它用于复制MyDBobj,但也有我想要的额外方法,例如{ {1}}。

Driving.py:

Driving.GetTachometerReading()

然后,为了完成子索引(class DrvClass( MyDB ): def __init__(self, MyDBobj): self.attribute1 = MyDBobj.attr1 self.attribute2 = MyDBobj.attr2 .... # copy all attribute values! def GetTachometerReading(self): .... #some function here ),在MyDBobj.Driving.GetTach()模块中,我通过Driving.py方法添加到Driving()类>

MyDB

现在,用户可以执行:def temp_driving(self): return DrvClass( self ) # pass the MyDBobj MyDB.Driving = temp_driving # add the above method to the MyDB class ,其中MyDBobj.Driving().GetTachometerReading()返回具有新MyDBobj.Driving()功能的新DrvClass对象。我不喜欢我必须将GetTachometer()称为函数。

您如何看待 - 有更好/更简单的方法吗?

之所以我希望MyDB类是分开的,是因为我们的访问方法可能会改变,而不会改变分析功能(驾驶/步行),反之亦然。因此,我不想直接将MyDB访问技术添加到单独的Driving& amp;步行模块。

提前感谢您的圣人建议!

1 个答案:

答案 0 :(得分:0)

我想我可能会在客户端使用不同的访问方法。如果客户端使用这样的协议:

result = myDBobj.Driving_GetTachometerReading()

然后可以直接将此名称添加到子模块Driving.py中的类中:

import pyMyDB

def GetTachometerReading(self):
    # self will be the MyDB instance

pyMyDB.MyDB.Driving_GetTachometerReading = GetTachometerReading

但是,如果你按照你的方法进行设置,那么我认为它可以得到改进。实际上,你为每次调用Driving函数创建了一个新的Driving实例,但这并不好。但是,我们需要在实例化MyDB本身时创建一个实例。然而,这似乎很棘手,因为当时我们似乎并不知道要包含哪些子模块。我通过让每个子模块将其方法列表注入MyDB来解决这个问题。像这样:

pyMyDB:

import functools

class MyDB(object):

    submodule_methods = {}

    def __init__(self):
        for k,v in self.submodule_methods.items():
            self.__dict__[k] = SubmodulePointer(self,v)

        self.db_stuff = "test"


class SubmodulePointer(object):

    def __init__(self,db,methods):
        self.db = db
        for name,func in methods.items():
            self.__dict__[name] = functools.partial(func,db)

然后对于每个子模块,例如驾驶我们做:

import pyMyDB

def GetTachometerReading(self):
    # self here is the db instance, as if this was a method on the db
    print(self.db_stuff)

pyMyDB.MyDB.submodule_methods["Driving"] = {"GetTachometerReading":GetTachometerReading}

然后客户可以这样做:

import pyMyDB
import Driving

m = pyMyDB.MyDB()

m.Driving.GetTachometerReading()

如你所愿。一种更简单的方法,稍微更传统的风格就是让驾驶成为一个属于自己的类:

pyMyDB:

import functools

class MyDB(object):

    submodule_classes = []

    def __init__(self):
        for c in self.submodule_classes:
            self.__dict__[c.__name__] = c(self)

        self.db_stuff = "test"

然后对于每个子模块,例如驾驶我们做:

import pyMyDB

class Driving(object):

    def __init__(self,db):
        self.db = db

    def GetTachometerReading(self):
        # self here is the Driving instance,
        # but we have access to the db
        print(self.db.db_stuff)

pyMyDB.MyDB.submodule_classes.append(Driving)

这意味着Driving类中的方法看起来不像MyDB上的方法,但这可能是一个优势。我不确定这是否是你想要的。