dir()与uu getattr_uu一起执行什么样的python魔术?
下面是python 2.7和MySQLDB1.2.3中的内容 我需要一个类包装器来为不支持它的对象添加一些属性(带有dir()与uu getattr_uu一起执行什么样的python魔术?,python,python-2.7,Python,Python 2.7,下面是python 2.7和MySQLDB1.2.3中的内容 我需要一个类包装器来为不支持它的对象添加一些属性(带有\uuuu插槽的类和/或一些用C编写的类),所以我得出了如下结论: class Wrapper(object): def __init__(self, obj): self._wrapped_obj = obj def __getattr__(self, obj): return getattr(self._wrapped_obj
\uuuu插槽的类和/或一些用C编写的类),所以我得出了如下结论:
class Wrapper(object):
def __init__(self, obj):
self._wrapped_obj = obj
def __getattr__(self, obj):
return getattr(self._wrapped_obj, attr)
我原以为对我的Wrapper
实例调用的dir()
内置函数应该只返回object pluswrapped\u obj
继承的名称,我发现大多数情况下都是这样,但并非所有情况都是这样。我用一个定制的旧样式类、一个定制的新样式类和一些内置类尝试了这一点,它总是这样工作:我发现的唯一例外是当包装对象是类的实例时\u mysql.connection
。在本例中,我的对象上的dir()
碰巧也知道附加到包装连接对象的所有方法名
我在python文档中读到了关于dir
,这种行为似乎是合法的:dir
应该返回一个“有趣的名称”列表,而不是实例的“真实”内容。但我真的不明白它是如何做到这一点的:它实际上理解我的\uuu getattr\uuuu
的实现,并解析为附加项?如果这是真的,为什么只使用该连接
类,而不使用更简单的dict
下面是一些粘贴的代码,作为这种奇怪行为的示例:
>>> from _mysql import connection
>>> c = connection(**connection_parameters)
>>> c
<_mysql.connection open to '127.0.0.1' at a16920>
>>>
>>> dir(c)
['affected_rows', 'autocommit', 'change_user', 'character_set_name', 'close', 'commit', 'dump_debug_info', 'errno', 'error', 'escape', 'escape_string', 'field_count', 'get_character_set_info', 'get_host_info', 'get_proto_info', 'get_server_info', 'info', 'insert_id', 'kill', 'next_result', 'ping', 'query', 'rollback', 'select_db', 'set_character_set', 'set_server_option', 'shutdown', 'sqlstate', 'stat', 'store_result', 'string_literal', 'thread_id', 'use_result', 'warning_count']
>>>
>>> w = Wrapper(c)
>>> dir(w)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattr__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_wrapped_obj', 'affected_rows', 'autocommit', 'change_user', 'character_set_name', 'close', 'commit', 'dump_debug_info', 'errno', 'error', 'escape', 'escape_string', 'field_count', 'get_character_set_info', 'get_host_info', 'get_proto_info', 'get_server_info', 'info', 'insert_id', 'kill', 'next_result', 'ping', 'query', 'rollback', 'select_db', 'set_character_set', 'set_server_option', 'shutdown', 'sqlstate', 'stat', 'store_result', 'string_literal', 'thread_id', 'use_result', 'warning_count']
>>>
>>> d = Wrapper({})
>>> dir(d)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattr__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_wrapped_obj']
>>>
来自mysql导入连接的>>
>>>c=连接(**连接参数)
>>>c
>>>
>>>处长(c)
[‘受影响的行’、‘自动提交’、‘更改用户’、‘字符集名称’、‘关闭’、‘提交’、‘转储调试信息’、‘错误’、‘转义’、‘转义字符串’、‘字段计数’、‘获取字符集信息’、‘获取主机信息’、‘获取协议信息’、‘获取服务器信息’、‘插入id’、‘杀死’、‘下一个结果’、‘ping’、‘查询’、‘回滚’、‘选择数据库’、‘设置字符’et“,”设置服务器选项“,”关机“,”sqlstate“,”统计“,”存储结果“,”字符串文字“,”线程id“,”使用结果“,”警告计数“]
>>>
>>>w=包装器(c)
>>>署长(西)
“UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU,”UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU","大小","str","子类钩子","weakref","包装对象","受影响行","自动提交","更改用户","字符集"名称"“,”关闭“,”提交“,”转储调试信息“,”错误“,”转义“,”转义字符串“,”字段计数“,”获取字符集信息“,”获取主机信息“,”获取协议信息“,”获取服务器信息“,”信息“,”插入id“,”杀死“,”下一个结果“,”ping“,”查询“,”回滚“,”选择数据库“,”设置字符集“,”设置服务器选项“,”关机“,”sqlstate“,”存储“,”esult',string\u literal',thread\u id',use\u result',warning\u count']
>>>
>>>d=包装器({})
>>>署长(丁)
“UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU,”UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU","大小","str","子类钩子","weakref","包装"obj"
>>>
Python 2中有两个不推荐使用的属性;它们旨在支持扩展类型(C定义的对象)上的dir()
:
对象。方法
自版本2.2以来已弃用:使用内置函数dir()
获取对象属性的列表。此属性不再可用
对象。\uuuu成员\uuuu
自版本2.2以来已弃用:使用内置函数dir()获取对象属性的列表。此属性不再可用
这些属性已从Python 3中删除,但这是因为您的连接对象(至少在您使用的旧版本中)仍然提供了一个\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu方法
属性,该属性可通过\uuuuuuuuuuuuuuu
如果将print
语句添加到\uuu getattr\uuu
方法中,您将看到正在访问的属性:
>>> class Wrapper(object):
... def __init__(self, obj):
... self._wrapped_obj = obj
... def __getattr__(self, obj):
... print 'getattr', obj
... return getattr(self._wrapped_obj, attr)
...
>>> dir(Wrapper({}))
getattr __members__
getattr __methods__
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattr__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_wrapped_obj']
对于新样式的对象,dir()
支持的较新样式仅在类型上正确查找,因此您不会看到在此处访问该类型
这表明在1.2.4 beta 1的大型Python 3兼容性更新中删除了这些属性。我无法真实再现您在Python 2.7和MySQLdb上看到的内容dir(w)
不包括c
中的名称。您确定没有在包装器上包含返回dir(self.\u wrapped\u obj)
的方法吗?是的,我使用包装器类测试了粘贴的输出,就像上面定义的那样导入什么;打印mysql.version\u info
生成?(1,2,3,'final',0)