0

如何创建一个字典类“D”来存储某些类“A”的实例并继承“A”方法的包装版本?

例如,假设 a = A() 和 a.first() 是一个对 'a' 执行某些操作并返回某个对象的函数。然后我希望 d = D({'k0': a0, 'k1': a1}) 有一个属性 d.first() 返回 {'k0': a0.first(), 'k1': a1.first ()} 并更改 a0 和 a1 中的基础数据,就像调用 first() 一样。

此外,我只想公开 dict 类中尚不存在的方法(可能还有属性)(没有踩踏),并且我想动态地执行此操作(没有 A 的方法的硬编码,我已经知道如何键入所有方法是手工出来的)。如果以某种方式更容易,也许考虑只处理不以'_'开头的方法。

此外,我希望“D”根据返回类型(后处理、包装任何内容)对调用的输出进行一些处理。

看起来这可能是一个坏主意,但我只想了解有哪些方法。从我目前的阅读来看,似乎我可以使用多重继承并编写自己的__new__函数或使用元类做其他事情。但传说是,__new__除非你是大师,否则你通常不应该乱来,所以这让我犹豫了。这样做有一些装饰技巧吗?我想我也可以使用检查模块来遍历类“A”,但这感觉就像黑客。

更新:作为一个非常具体的例子。想象一下,我有一个 pandas.DataFrames 字典,并且我希望该集合尽可能像单个 DataFrame 一样出现和表现,甚至可以在 iPython 中使用选项卡完成方法(而且我没有使用 pandas.Panel)。为简单起见,只考虑只读行为(索引和选择),像 d.ix[0:10] 和 d.mean() 应该从将函数应用于字典中的所有帧而返回一些东西,而 d['k0 '] 应该返回与键 'k0' 对应的字典中的值。硬编码和getattr的组合可以满足我的要求,但我正在探索如何用更少的硬编码来完成。

我认为这是一个常见的设计问题,您希望动态生成一个行为类似于它包含的对象的可迭代对象。

4

2 回答 2

1

这些中的每一个都在有限的测试中起作用:

#! /usr/bin/python3
class D(dict):
    def __getattr__(self, name):
        return lambda *args, **kw: {
            k:getattr(v,name)(*args, **kw) for k,v in self.items() }

class D(dict):
    def __getattr__(self, name):
        def proxy(*args, **kw):
            d2 = {k:getattr(v,name)(*args, **kw) for k,v in self.items()}
            # Post-process if required
            return d2
        return proxy

d = D()

d['k1']='a1'
d['k2']='a2'
d['k3']='33'

print(d.capitalize())  # No-arg form passed to str, not dict
print(d.replace('a', 'Hello')) # Arguments
print(d.get('k1'))  # .get() satisified by dict, not str
于 2013-09-03T04:32:55.150 回答
0

这是一个有点奇怪的问题,但它在很大程度上取决于“D”在结构上是什么。如果 D 只是一个数据结构,那么将字典与对象打包在一起是完全有效的,下标并调用函数,如下所示:

class A(object):
   def __init__(self,x):
       self.x = x
   def first(self):
       return self.x

a = A(7)
b = A(3)
d = {'X':a,'Y':b}
print d['X'].first()

除此之外,如果您想要所有“第一”,那么您可以执行以下操作:

firsts = {}
for i,j in d:
    firsts[i]=j.first()

但是,您的挑战似乎有点复杂,而且不安全:如果字典中的对象有keys()方法怎么办?哪个优先,如果是字典,我如何访问keys()内容的方法?

我的建议是用更多细节重新定义或重新提出问题。首先,字典中的对象代表什么?更重要的是,字典代表什么?

于 2013-09-03T03:04:46.333 回答