免费注册 查看新帖 |

Chinaunix

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

请问 "luffy.deng": 如何访问属性(一句话描述不清楚) [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-08-22 22:55 |只看该作者 |倒序浏览
问题(简化版):
     用户随意的填写一个字典,例如这样:
  1. foo = {'a': 1,
  2.        'b': 2,
  3.        'c': {'a': 22,
  4.              'b': 23
  5.            }
  6.        }
复制代码
这是一个函数,名字get_value,下面会用到:
  1. def get_value(x):
  2.     return x + rand()
复制代码
用户可以输入任意深度的,任意key的字典,也就是这个dict可以任意的大,还有就是这个dict的key可以是任意的,也就是相当于这个dict可以任意构造。
我想要这样的效果:
  1. bar = you_define_class(foo)
  2. print bar.c.a #我希望打印的结果就类似于get_value(foo['c']['a'])
复制代码
这个会用到python里面的data decriptor,但是我有点崩溃,没有看懂。

论坛徽章:
0
2 [报告]
发表于 2010-08-22 23:02 |只看该作者
回复 1# tianshizhiluan
我想你想实现的就是根据用户输入的字典 来动态定义一个类 ,我想这正是 type('klass',(object,),d)的用途。

论坛徽章:
0
3 [报告]
发表于 2010-08-22 23:36 |只看该作者

  1. def dictToObject(d):
  2.     class dct(object):
  3.         def __init__(self, d):
  4.             self.__d = d
  5.         def __getattr__(self, k):
  6.             try:
  7.                 result = self.__d.get(k)
  8.                 if isinstance(result, dict):
  9.                     return dictToObject(result)
  10.                 else:
  11.                     return result
  12.             except:
  13.                 raise AttributeError
  14.     return dct(d)
复制代码

论坛徽章:
0
4 [报告]
发表于 2010-08-22 23:37 |只看该作者
回复  tianshizhiluan
我想你想实现的就是根据用户输入的字典 来动态定义一个类 ,我想这正是 type('klas ...
luffy.deng 发表于 2010-08-22 23:02



    杀鸡用牛刀

论坛徽章:
0
5 [报告]
发表于 2010-08-23 09:02 |只看该作者
回复 4# shhgs
相对于递归函数,我个人更喜欢用牛刀的写法,当然只是个人爱好。

论坛徽章:
0
6 [报告]
发表于 2010-08-23 13:37 |只看该作者
web.py有一个类
  1. class Storage(dict):
  2.     """
  3.     A Storage object is like a dictionary except `obj.foo` can be used
  4.     in addition to `obj['foo']`.
  5.    
  6.         >>> o = storage(a=1)
  7.         >>> o.a
  8.         1
  9.         >>> o['a']
  10.         1
  11.         >>> o.a = 2
  12.         >>> o['a']
  13.         2
  14.         >>> del o.a
  15.         >>> o.a
  16.         Traceback (most recent call last):
  17.             ...
  18.         AttributeError: 'a'
  19.    
  20.     """
  21.     def __getattr__(self, key):
  22.         try:
  23.             return self[key]
  24.         except KeyError, k:
  25.             raise AttributeError, k
  26.    
  27.     def __setattr__(self, key, value):
  28.         self[key] = value
  29.    
  30.     def __delattr__(self, key):
  31.         try:
  32.             del self[key]
  33.         except KeyError, k:
  34.             raise AttributeError, k
  35.    
  36.     def __repr__(self):     
  37.         return '<Storage ' + dict.__repr__(self) + '>'
复制代码

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
7 [报告]
发表于 2010-08-23 16:37 |只看该作者
本帖最后由 tianshizhiluan 于 2010-08-23 16:42 编辑

恩,已经实现了,我写了个通用的函数to_obj(有点函数式编程的意思),可以用来完成所有类似的功能,当然还是那样:动态生成。下面是代码。感谢 """ luffy.deng """
新问题:对于一个大的dict,需要调用很多次type来生成类,我不知道这样是不是会导致性能降低很多,或者可以找到一个更好的方法来解决这个问题?谁有解决方案吗?请上代码。谢谢
  1. #! /usr/bin/env python                                                                                                                                                                  

  2. import types

  3. foo = {'a': 1,
  4.        'b': 2,
  5.        'c': {'a': 22,
  6.              'b': 23
  7.            }
  8.        }


  9. def test_key(d):
  10.     return isinstance(d, types.IntType)


  11. class Data(object):
  12.     def __init__(self, value):
  13.         self._value = value
  14.         pass

  15.     def __get__(self, obj, type=None):
  16.         return self._value + 2

  17.     pass


  18. def to_obj(dct, test_key, descriptor):
  19.     x = type('xo0pP', (object,), dict())

  20.     for key in dct.keys():
  21.         if test_key(dct[key]):
  22.             setattr(x, key, descriptor(dct[key]))
  23.             pass
  24.         else:
  25.             setattr(x, key, to_obj(dct[key], test_key, descriptor))
  26.             pass
  27.         pass
  28.     return x


  29. if __name__ == "__main__":
  30.     x = to_obj(foo, test_key, Data)
  31.     print x.a      # 3                                                                                                                                                                  
  32.     print x.c.b    # 25                                                                                                                                                                 

复制代码

论坛徽章:
0
8 [报告]
发表于 2010-08-23 22:58 |只看该作者
回复 7# tianshizhiluan


    看了你的代码,我不禁又想起了那句名言。

好的编程语言,能让你写出优雅的代码,但是谁都挡不住你去写烂代码。

论坛徽章:
0
9 [报告]
发表于 2010-08-23 22:59 |只看该作者
回复 5# luffy.deng


    对于你,恐怕得改成,谁都挡不住你去教别人去写烂代码。

论坛徽章:
0
10 [报告]
发表于 2010-08-24 08:06 |只看该作者
本帖最后由 luffy.deng 于 2010-08-24 08:10 编辑

回复 9# shhgs
必须得说你的代码写的好,但这个问题不见得非得用你的办法。不但用type可以解决,而且还可以用元类来避免对动态生成的类实例化。
为什么不用你的办法就是烂办法?提一个不一样的解决问题的途径就是教别人写烂代码?
  1. d= {'a':1,
  2.     'b':2,
  3.     'c':{'e':1,
  4.          'f':2
  5.          }
  6.     }
  7. class Meta(type):
  8.     def __getattribute__(self,name):
  9.         _attr=object.__getattribute__(self,name)
  10.         if isinstance(_attr,dict):
  11.             setattr(self,name,Meta('',(object,),_attr))
  12.             _attr=object.__getattribute__(self,name)
  13.         return _attr
  14. foo=Meta('foo',(object,),d)
  15. print foo.c.g
复制代码
实际上你写的那段还是有点问题的,对于一个不存在的属性比如foo.c.xxxx会返回None而不是抛出AttributeError异常。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP