2011-05-21 17 views
7

पर विशेषताओं को जोड़ें, क्या मैं गतिशील रूप से एक नई शैली के वर्ग (object से प्राप्त) के उदाहरणों में विशेषताओं को जोड़ सकता हूं?पायथन: गतिशील रूप से नई शैली के वर्ग/obj

विवरण:

मैं sqlite3.Connection का एक उदाहरण के साथ काम कर रहा हूँ। बस वर्ग को विस्तारित करना एक विकल्प नहीं है क्योंकि मुझे कन्स्ट्रक्टर को कॉल करके इंस्टेंस नहीं मिलता है; मुझे sqlite3.connect() पर कॉल करके मिलता है।

एक रैपर बनाने से मुझे जो कोड लिख रहा है, उसके लिए मुझे बहुत अधिक बचत नहीं होती है।

अजगर 2.7.1

संपादित

सही जवाब सब। लेकिन मैं अभी भी अपने लक्ष्य तक नहीं पहुंच रहा हूं; sqlite3.Connection बार के उदाहरण निम्नलिखित तरीकों से विशेषताओं को सेट करने के मेरे प्रयास (जैसे object के उदाहरण)। मुझे हमेशा एक विशेषता प्राप्त होती है:

> 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 क्या उपयोग कर रहा है। लेकिन यह एक सी दिनचर्या हो सकता है, इस मामले में आपको इसे किसी भी तरह लपेटने के लिए मजबूर किया जाएगा। –

+1

+1। यहां तक ​​कि 'वस्तु।__setattr __ (conn, 'a', 'foo') 'विशेषता Error बढ़ाता है। दिलचस्प सवाल! – EOL

उत्तर

5

हां, जब तक कि कक्षा __slots__ का उपयोग नहीं कर रही है या __setattr__, या एक आंतरिक पायथन कक्षा, या पाइथन कक्षा को ओवरराइड (आमतौर पर सी में) द्वारा ओवरराइड करके विशेषता लेखन को रोकती है।

आप हमेशा एक विशेषता सेट करने का प्रयास कर सकते हैं। गंभीर रूप से अजीब __setattr__ कार्यान्वयन के अलावा, ऊपर वर्णित प्रकारों में से किसी एक के वर्ग के उदाहरण के लिए एक विशेषता निर्दिष्ट करने से AttributeError बढ़ाना चाहिए।

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

तो, वास्तव में यह है कि ऐसा करना संभव हो रहा है: इन मामलों में, आप इस प्रकार का आवरण का उपयोग करने, होगा:

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 या 'ऑब्जेक्ट' के उदाहरणों के लिए काम नहीं करता है। (ऊपर संपादित देखें।) कोई मदद? – JellicleCat

+0

@JellicleCat दोनों "आंतरिक पायथन कक्षा" के अंतर्गत आते हैं। मैंने एक रैपर के साथ जवाब बढ़ाया। आपने प्रश्न में एक का उपयोग करने का उल्लेख किया है; लेकिन मुझे यकीन नहीं है कि यह समस्या का समाधान क्यों नहीं करेगा। यदि यह रैपर काम नहीं करता है, तो कृपया उस परिदृश्य के साथ अपना प्रश्न बढ़ाएं (या यहां टिप्पणी करें) जिसमें यह विफल रहता है। – phihag

-1

यहां जादू शब्द "बंदर पैचिंग" है। उदाहरण के साथ यहां an SO answer है।

+0

बंदर पैचिंग आमतौर पर एक वर्ग के सभी उदाहरणों को बदलने का मतलब है। ऐसा लगता है कि जेल्लिकल कैट सिर्फ एक विशिष्ट उदाहरण के गुणों को बदलना चाहता है। – phihag

+0

यह वास्तव में बिंदु की ओर है, चार्ली, तो धन्यवाद। फिर भी, यह मुझे उस समस्या से दूर नहीं करता है जहां मुझे अपने स्वयं के उपकरणों और अन्य दो प्रतिक्रियाओं से बचाया गया है। – JellicleCat

2

सरल प्रयोग।

अद्यतन:
लेकिन documentation:SQLite से तो ऐसा लगता है कि तुम सच में लपेट की जरूरत है, एक सी पुस्तकालय है कि ... है।

+0

अब मैं देखता हूं कि आप सही हैं, लेकिन यह sqlite3.Connection या 'ऑब्जेक्ट' के उदाहरणों के लिए काम नहीं करता है। (ऊपर संपादित देखें।) कोई मदद? – JellicleCat

+0

@JellicleCat: मेरा उत्तर अपडेट किया गया। – eat

0
conn.a = 'foo', 

या किसी गतिशील काम, मान्य है अगर Conn

<type 'classobj'>. 

हालात की तरह है:

c=object() 
    c.e=1 

एक गुण त्रुटि को बढ़ा देंगे। दूसरी तरफ: पायथन आपको शानदार मेटाक्लास प्रोग्रामिंग करने की अनुमति देता है:

>>>from new import classobj 
    >>>Foo2 = classobj('Foo2',(Foo,),{'bar':lambda self:'bar'}) 
    >>>Foo2().bar() 
    >>>'bar' 
    >>>Foo2().say_foo() 
    >>>foo 
संबंधित मुद्दे