2011-05-21 38 views
7

我可以动态属性添加到一个新式类(一个从object派生)的实例?的Python:动态属性添加到新式类/ OBJ

详细信息:

我正在使用sqlite3.Connection的实例。简单地扩展类不是一种选择,因为我没有通过调用构造函数来获取实例;我打电话给sqlite3.connect()

建立一个包装不救我多少散装我写的代码。

的Python 2.7.1

编辑

正确答案全部。但我仍然没有达到我的目标; sqlite3.Connection栏的实例我尝试以下列方式设置属性(就像object本身的实例一样)。我总是得到一个AttributeError:

> conn = sqlite3.connect([filepath]) 
> conn.a = 'foo' 
Traceback (most recent call last): 
    File "<pyshell#2>", line 1, in <module> 
    conn.a = 'foo' 
AttributeError: 'object' object has no attribute 'a' 
> conn.__setattr__('a','foo') 
Traceback (most recent call last): 
    File "<pyshell#2>", line 1, in <module> 
    conn.__setattr__('a','foo') 
AttributeError: 'object' object has no attribute 'a' 

帮助?

+0

你可以检查实际的__dict__来找出sqlite3正在使用什么。但是这可能是一个C例程,在这种情况下,你将被迫以某种方式包装它。 – 2011-05-21 16:35:28

+1

+1。即使是对象。__setattr __(conn,'a','foo')'引发AttributeError。有趣的问题! – EOL 2011-05-21 16:44:01

回答

5

是的,除非班级使用__slots__或通过覆盖__setattr__或内部Python类或本机实施的Python类(通常以C语言)实现防止属性写入。

你总是可以尝试设置的属性。除了严重奇怪的__setattr__实现外,将属性分配给上述类型的类的实例应引发AttributeError。 在这种情况下,你必须使用包装,像这样:

class AttrWrapper(object): 
    def __init__(self, wrapped): 
    self._wrapped = wrapped 
    def __getattr__(self, n): 
    return getattr(self._wrapped, n) 
conn = AttrWrapper(sqlite3.connect(filepath)) 
+0

我现在看到你是正确的,但它不适用于sqlite3.Connection或'object'本身的实例。 (请参阅上面的修改)任何帮助? – JellicleCat 2011-05-21 16:24:06

+0

@JellicleCat都属于“内部Python类”。我用封套扩展了答案。你提到在问题中使用一个;但我不确定为什么它不能解决问题。如果这个包装不起作用,请将您的问题(或在这里注释)与其中失败的情况进行比较。 – phihag 2011-05-21 16:53:07

-1

魔语这里是“猴子补丁”。这里有an SO answer的例子。

+0

猴子修补通常意味着更改班级的所有实例。它看起来像JellicleCat只是想改变一个特定实例的属性。 – phihag 2011-05-21 15:19:47

+0

这实际上是指向查理,所以谢谢你。尽管如此,它并没有让我摆脱我被我自己的设备和其他两个响应所遗留的问题。 – JellicleCat 2011-05-21 16:29:49

2

简单的实验:

In []: class Tst(object): pass 
    ..: 
In []: t= Tst() 
In []: t.attr= 'is this valid?' 
In []: t.attr 
Out[]: 'is this valid?' 

所以,实际上它似乎是可能做到这一点。

更新:
但是从documentation:SQLite是一个C库...,这样看来,你真的需要把它包起来。

+0

我现在看到你是正确的,但它不适用于sqlite3.Connection或'object'本身的实例。 (请参阅上面的修改)任何帮助? – JellicleCat 2011-05-21 16:25:40

+0

@JellicleCat:更新了我的答案。 – eat 2011-05-21 16:49:52

0
conn.a = 'foo', 

或任何动态分配是有效的,如果conn是

<type 'classobj'>. 

事情是这样:

c=object() 
    c.e=1 

会引发一个属性错误。另一方面:Python允许你做梦幻般的Metaclass编程:

>>>from new import classobj 
    >>>Foo2 = classobj('Foo2',(Foo,),{'bar':lambda self:'bar'}) 
    >>>Foo2().bar() 
    >>>'bar' 
    >>>Foo2().say_foo() 
    >>>foo