Pymongo数据库对象客户端拥有任何属性?

时间:2017-09-12 16:02:36

标签: python mongodb pymongo

我正在浏览PyMongo tutorial并且有一件我不理解的事情。

我们证明我们可以创建这样的数据库集合:

>>>client = MongoClient()   
>>>print(client)

MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True) 

>>>db = client.test_database
>>>print(db)

Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'test_database')

>>>collection = db.test_collection #posts is the collection.
>>>print(collection)

Collection(Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'test_database'), 'test_collection')

我最初的想法是:"他们是否确保为客户端添加test_database属性,为数据库添加test_collection属性以使其与教程一起使用?&# 34;但进一步的实验告诉我,我可以使用任何"属性名称"以这种方式创建数据库和集合。我请求!例如:

>>>client = MongoClient()
>>>db = client.foo
>>>print(db)

Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'foo')

>>>collection = db.bar
>>>print(collection)

Collection(Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'foo'), 'bar')

这在Python中是如何工作的?我通过阅读GitHub存储库中的pymongo文件试图理解它,但新手很难理解。

2 个答案:

答案 0 :(得分:2)

MongoClient会覆盖“魔法”方法__getattr__。每当您访问MongoClient对象上的属性时,该对象实际上不是对象的属性或属性,例如当您访问“test_database”时,Python解释器会调用:

client.__getattr__("test_database")

The implementation of MongoClient.__getattr__然后创建一个Database对象并返回它。

数据库还会覆盖__getattr__以返回任何名称的Collection。

这两个类都会覆盖__getitem__,以便括号访问起作用:

client["test_database"]

See the __getattr__ docs here

答案 1 :(得分:1)

您需要在班级中实施__getattr__方法才能使其正常运行 简单来说 - 每当您访问未在类中定义的属性时,将调用__getattr__方法(实际上它稍微复杂一些)。见下面的例子:

class Database(object):

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

    def __getattr__(self, name):
        return Collection(name)

class Collection(object):

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

    def __repr__(self):
        return '<Collection name={0}>'.format(self.name)

>>> db = Database('www.example.com')
>>> db.host
'example.com'
>>> db.foo
<Collection name=foo>
>>> db.bar
<Collection name=bar>

您可以在此处详细了解__getattr__Python: how to implement __getattr__()?