免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2984 | 回复: 3
打印 上一主题 下一主题

一个python instance属性的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-07-17 16:25 |只看该作者 |倒序浏览

今天看了一下MongoDB的python driver - pymongo,连接数据库的代码是

from pymongo import MongoClient

client = MongoClient('127.0.0.1', 27017)

接下来要获得一个Database的实例
db = client.mydb
或者
db = client['mydb']

'mydb'是db名字,

这里我就搞不懂了, client是pymongo.mongo_client.MongoClient的实例,
>>> type(client)
<class 'pymongo.mongo_client.MongoClient'>

对于db = client.mydb, mydb应该是实例属性, 但事实上实例并没有这个属性。 比如,db server端没有mydb这个db,也可以这样写,然后可以insert创建一个名为‘mydb’的新db。

对于db = client['mydb'], 这个就更困惑了。

请教一下这是使用的python的什么功能才能做到这个?

多谢

论坛徽章:
0
2 [报告]
发表于 2013-07-17 17:41 |只看该作者
明白了,是Database类重载了__getattr__()就可以了。

论坛徽章:
0
3 [报告]
发表于 2013-07-17 21:40 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
4 [报告]
发表于 2013-07-17 22:46 |只看该作者
本帖最后由 sardinescn 于 2013-07-17 23:48 编辑

还是跟重载有关系, 你的01.png里面就是在重载__getattr__()

我们先看db = client.mydb。这个地方的关键是为何能引用一个不存在的属性。
看一个简化的类定义
  1. class B(object):
  2.     pass

  3. y = B()
  4. print y.mydb  
复制代码
很明显,print y.mydb 会抛出异常:AttributeError: 'B' object has no attribute 'mydb'

但我们如果重载__getattr__(), 就可以让它没有异常:
  1. # override __getattr__
  2. class B(object):
  3.     def __getattr__(self, name):
  4.         return name

  5. y = B()
  6. print y.mydb
复制代码
当python解释器遇到y.mydb是,它首先到y的字典里面去查找mydb的属性,如果查找不到,会调用__getattr__(), 默认的__getattr__()应该是空的, 所以找不到mydb这个属性,抛出异常。 但是如果重载了__getattr__(), 上面的代码是直接返回name, pymongo的代码是创建一个collection并返回。 这样就没有异常了。 而且pymongo通过这种方式来创建一个collection.

接着再看db = client['mydb']
这里我们首先要解决的是怎样通过下标来获取类属性。
  1. class A(object):
  2.     def __init__(self):
  3.         self.a = 1
  4.         self.b = 2
  5.         self.c = 3

  6. x = A()
  7. print x.a
  8. print x['a']
复制代码
在执行print x['a']的时候会抛出异常告诉你 class A is unsubscriptable.
我们可以重载__getitem__()使得能够用下标获取类的属性
  1. class A(object):
  2.     def __init__(self):
  3.         self.a = 1
  4.         self.b = 2
  5.         self.c = 3
  6.         
  7.     def __getitem__(self, name):
  8.         return self.__getattribute__(name)
复制代码
这样就可以了。

注意pymongo里面在__getitem__()中调用的是重载的__getattr__(), 所以db=client.mydb和db=client['mydb']就有相同的效果了。


您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP