2011-05-21 48 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