从类对象继承属性的类对象的python dict

Posted

技术标签:

【中文标题】从类对象继承属性的类对象的python dict【英文标题】:python dict of class objects that inherits attributes from class objects 【发布时间】:2013-09-06 03:41:26 【问题描述】:

如何创建一个字典类“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”,但这感觉就像 hack。

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

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

【问题讨论】:

你看过__getattr__吗? @BrenBarn 您的意思是自己通过检查 dict 上的 getattr 然后检查“A”来处理继承?我想这是一个更简单的解决方案。 【参考方案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

【讨论】:

getattr 似乎适用于函数,但不适用于 d.ix[0:10] 等基本上具有 getitem 方法的属性。我想这可以通过某种方式手动检查。【参考方案2】:

这是一个有点奇怪的问题,但很大程度上取决于“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() 方法?

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

【讨论】:

字典优先。如果您想访问对象的键,那么您只需执行 d['k0'].keys() (没有提供便利功能)。用例基本上是 iPython。考虑一组表(或 DataFrame),您希望在其中单独存储它们(主要是不相交的列),但希望对它们进行操作,就好像它们是一个表一样。

以上是关于从类对象继承属性的类对象的python dict的主要内容,如果未能解决你的问题,请参考以下文章

面向对象的深刻理解

面向对象

python笔记58-类里面的__dict__属性

Python笔记:字典类属性对象实例继承

python之旅:面向对象之继承与派生

python面向对象之继承