2008-10-17 11 views
9

मैं कुछ कमांड लाइन विकल्प रखने के लिए एक छोटी सी बंद पायथन ऑब्जेक्ट बनाना चाहता हूं। मैं कुछ इस तरह करना चाहते हैं:एक छोटा सा बंद पायथन ऑब्जेक्ट बनाने का एक आसान तरीका क्या है?

options = ?????? 
options.VERBOSE = True 
options.IGNORE_WARNINGS = False 

# Then, elsewhere in the code... 
if options.VERBOSE: 
    ... 

बेशक मैं एक शब्दकोश का उपयोग कर सकता है, लेकिन options.VERBOSE अधिक पठनीय और आसान options['VERBOSE'] से टाइप करने के लिए है।

मैं सोचा है कि मैं,

options = object() 

ऐसा करने में सक्षम होना चाहिए, क्योंकि object सभी वर्ग की वस्तुओं के आधार प्रकार है और इसलिए कोई विशेषताओं के साथ एक वर्ग की तरह कुछ किया जाना चाहिए। लेकिन यह काम नहीं करता है, क्योंकि एक वस्तु object() का उपयोग कर एक __dict__ सदस्य नहीं है बनाया है, और इसलिए भी इसे करने के लिए गुण नहीं जोड़ सकते हैं:

options.VERBOSE = True 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'object' object has no attribute 'VERBOSE' 

क्या एक वस्तु बनाने के लिए सबसे आसान "pythonic" तरीका है कि इस तरह इस्तेमाल किया जा सकता है, अधिमानतः एक अतिरिक्त सहायक वर्ग बनाने के बिना?

उत्तर

8

अपनी आवश्यकताओं को देखते हुए, मैं कहेंगे कस्टम वर्ग अपने सबसे अच्छे शर्त है:

class options(object): 
    VERBOSE = True 
    IGNORE_WARNINGS = True 

if options.VERBOSE: 
    # ... 

, एक और दृष्टिकोण, एक अलग मॉड्यूल का उपयोग करेंगे पूरा होने के लिएयानी आपके विकल्प डिफ़ॉल्ट को समाहित करने के लिए।

options.py:

VERBOSE = True 
IGNORE_WARNINGS = True 

फिर, main.py में:

import options 

if options.VERBOSE: 
    # ... 

यह अपनी स्क्रिप्ट से कुछ अव्यवस्था को दूर करने के सुविधा है। डिफ़ॉल्ट मान ढूंढना और बदलना आसान है, क्योंकि उन्हें अपने मॉड्यूल में बंद कर दिया जाता है। यदि बाद में आपका आवेदन बढ़ गया है, तो आप आसानी से अन्य मॉड्यूल से विकल्पों तक पहुंच सकते हैं।

यह एक ऐसा पैटर्न है जिसका मैं अक्सर उपयोग करता हूं, और अगर आप किसी भी मॉड्यूल से बड़े पैमाने पर बढ़ते हुए अपने अनुप्रयोग को ध्यान में रखते हैं तो दिल से अनुशंसा करेंगे। या, कस्टम क्लास से शुरू करें, और बाद में मॉड्यूल में विस्तार करें यदि आपका ऐप एकाधिक मॉड्यूल में बढ़ता है।

+0

यह बहुत ही अजीब नहीं होने के दौरान मैंने जो अनुरोध किया है उसके नजदीकी जैसा लगता है। और 'विकल्प' वर्ग में कोई अन्य विशेषता नहीं है जो भ्रमित होने की संभावना है। – mhagger

+0

मुझे लगता है कि इस तरह की कक्षा परिभाषा में VERBOSE डालना थोड़े व्यर्थ है क्योंकि यह इसे क्लास-वेरिएबल (उदाहरण आवृत्ति नहीं) के रूप में बनाता है AFAIK – hasen

+3

दरअसल, यह बात है। कक्षा को सिर्फ नामस्थान के रूप में उपयोग किया जा रहा है, ताकि आपको मूल्यों को प्राप्त करने के लिए कुछ भी चालू नहीं करना पड़े। –

14

collections module 2.6 में एक namedtuple समारोह हो गया है:

import collections 
opt=collections.namedtuple('options','VERBOSE IGNORE_WARNINGS') 
myoptions=opt(True, False) 

>>> myoptions 
options(VERBOSE=True, IGNORE_WARNINGS=False) 
>>> myoptions.VERBOSE 
True 

एक namedtuple, अपरिवर्तनीय है ताकि आप केवल क्षेत्र मान निर्दिष्ट जब आप इसे बना सकते हैं। , अपने दृष्टिकोण पर निर्भर करता है

class attrdict(dict): 
    def __init__(self, *args, **kwargs): 
     dict.__init__(self, *args, **kwargs) 
     self.__dict__ = self 

आप शायद लगता है कि यह या तो एक बड़ा है:

class options(object): 
    pass 

myoptions=options() 
myoptions.VERBOSE=True 
myoptions.IGNORE_WARNINGS=False 
>>> myoptions.IGNORE_WARNINGS,myoptions.VERBOSE 
(False, True) 
+0

मैं 'namedtuple' वर्ग के बारे में पता नहीं था, इसलिए संदर्भ के लिए धन्यवाद कर रहे हैं। लेकिन मुझे एक म्यूटेबल ऑब्जेक्ट चाहिए (उपयोगी, उदाहरण के लिए, कमांड लाइन प्रोसेसिंग के दौरान)। साथ ही, 'nametuple' इंस्टेंस का प्रारंभिकरण वास्तव में इस उद्देश्य के लिए उपयोग किए जाने वाले सभी पठनीय नहीं है। – mhagger

+0

यदि आप नामांकित दस्तावेज़ में देखते हैं, तो आप देखेंगे कि एक स्पष्ट प्रारंभिक विकल्प (अभी भी अपरिवर्तनीय, क्षमा करें), उदाहरण: "ऑप्ट (VERBOSE = True, IGNORE_WARNINGS = गलत)" – gimel

+0

नामांकित tuples असीमित रूप से शांत हैं। इस आलेख को http://www.artima.com/weblogs/viewpostP.jsp?thread=236637 और यह नुस्खा देखें यदि आप पाइथन 2.6 पर नहीं हैं http://code.activestate.com/recipes/500261/ –

5

मैं उपयोग attrdict:

पहले अजगर संस्करणों में, आप एक खाली वर्ग बना सकते हैं क्लेज या काफी चालाक। लेकिन जो कुछ भी आपको लगता है, यह अच्छा लग रही कोड के लिए पड़ता है, और एक dict साथ संगत है:

>>> ad = attrdict({'foo': 100, 'bar': 200}) 
>>> ad.foo 
100 
>>> ad.bar 
200 
>>> ad.baz = 'hello' 
>>> ad.baz 
'hello' 
>>> ad 
{'baz': 'hello', 'foo': 100, 'bar': 200} 
>>> isinstance(ad, dict) 
True 
+0

इसे आजमाएं : विज्ञापन ['foo-bar'] = 'oopsy' –

+1

@ जेरेमी - यह सुनिश्चित नहीं है कि समस्या क्या है: >>> विज्ञापन ['foo-bar'] = 'oopsy' >>> विज्ञापन {'baz' : 'हैलो', 'foo': 100, 'bar': 200, 'foo-bar': 'oopsy'} – davidavr

2

सरल davraamides's suggestion, एक इस्तेमाल कर सकते हैं निम्नलिखित:

class attrdict2(object): 
    def __init__(self, *args, **kwargs): 
     self.__dict__.update(*args, **kwargs) 

जो

  1. इतना क्लेडी नहीं है।

  2. dict के मानक तरीकों के साथ प्रत्येक ऑब्जेक्ट के नेमस्पेस को दूषित नहीं करता है; उदाहरण के लिए, ad.has_key को attrdict2 प्रकार की वस्तुओं के लिए परिभाषित नहीं किया गया है।

वैसे, यह और भी attrdict या attrdict2 के उदाहरण प्रारंभ करने में आसान है:

>>> ad = attrdict2(foo = 100, bar = 200) 

दी, attrdict2 एक dict साथ संगत नहीं है।

आप जादू प्रारंभ व्यवहार की जरूरत नहीं है, तो आप भी

class attrdict3(object): 
    pass 

ad = attrdict3() 
ad.foo = 100 
ad.bar = 200 

उपयोग कर सकते हैं लेकिन मैं अभी भी एक समाधान है कि एक सहायक वर्ग की आवश्यकता नहीं है के लिए उम्मीद की गई थी।

1

एक का उपयोग कर सकते

class options(object): 
    VERBOSE = True 
    IGNORE_WARNINGS = False 

options.VERBOSE = False 

if options.VERBOSE: 
    ... 

, वर्ग वस्तु ही उपयोग कर (वर्ग का एक उदाहरण नहीं है!) जगह अलग-अलग विकल्पों स्टोर करने के लिए के रूप में। यह terse है और सभी आवश्यकताओं को पूरा करता है, लेकिन यह वर्ग अवधारणा के दुरुपयोग की तरह लगता है। यदि उपयोगकर्ता ने options कक्षा को तुरंत चालू किया तो इससे भ्रम पैदा हो जाएगा।

(यदि विकल्प सुविधाजनक उपकरणों की वस्तुओं के कई उदाहरण की जरूरत थी, यह एक बहुत अच्छा समाधान हो सकता है -। वर्ग परिभाषा आपूर्ति मूलभूत मूल्यों, जो अलग-अलग मामलों में अधिरोहित जा सकता है)

1

बिल्कुल सरल वर्ग काम करने के लिए है:

class Struct: 
    def __init__(self, **entries): 
     self.__dict__.update(entries) 

बाद में यह रूप में इस्तेमाल किया जा सकता है: (के रूप में एक और टिप्पणी की

john = Struct(name='john doe', salary=34000) 
print john.salary 

namedtuple का सुझाव एड) एक और उन्नत कक्षा है जो आपको अधिक कार्यक्षमता प्रदान करती है। यदि आप अभी भी पायथन 2.5 का उपयोग कर रहे हैं, तो कार्यान्वयन 2.6 के namedtuple पर आधारित है http://code.activestate.com/recipes/500261/

6

यदि आप कक्षा को परिभाषित करने का आग्रह करते हैं, तो आप कुछ मौजूदा वर्गों का दुरुपयोग कर सकते हैं। अधिकांश वस्तुओं जो एक dict की जरूरत नहीं है करने के लिए "नई शैली" कक्षाएं हैं, लेकिन कार्यों मनमाना गुण कर सकते हैं:

>>> x = lambda: 0 # any function will do 
>>> x.foo = 'bar' 
>>> x.bar = 0 
>>> x.xyzzy = x 
>>> x.foo 
'bar' 
>>> x.bar 
0 
>>> x.xyzzy 
<function <lambda> at 0x6cf30> 

एक समस्या यह कार्यों को पहले से ही, कुछ चारित्रिक विशेषताओं है कि इतने dir (एक्स) एक छोटे से है गंदा:

>>> dir(x) 
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', 
'__get__', '__getattribute__', '__hash__', '__init__', 
'__module__', '__name__', '__new__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__', '__str__', 'foo', 
'func_closure', 'func_code', 'func_defaults', 'func_dict', 
'func_doc', 'func_globals', 'func_name', 'xyzzy'] 
+1

यह सुनिश्चित करता है कि ओपी वास्तव में क्या पूछ रहा था। –

3

बस विकल्प नामक मॉड्यूल बनाएं।पाई, और इसे आयात करें। वैश्विक चर के रूप में अपने डिफ़ॉल्ट विकल्प मानों को वहां रखें।

7

क्यों सिर्फ optparse का उपयोग नहीं: सर्वोत्तम प्रथाओं जाना

from optparse import OptionParser 
[...] 
parser = OptionParser() 
parser.add_option("-f", "--file", dest="filename", 
       help="write report to FILE", metavar="FILE") 
parser.add_option("-q", "--quiet", 
       action="store_false", dest="verbose", default=True, 
       help="don't print status messages to stdout") 

(options, args) = parser.parse_args() 

file = options.filename 
if options.quiet == True: 
    [...] 
4

के रूप में, तुम सच में David Eyk's answer में से कोई एक विकल्प के साथ बेहतर कर रहे हैं।

हालांकि, अपने सवाल का जवाब देने के लिए, आप एक बंद वर्ग type समारोह का उपयोग कर बना सकते हैं:

options = type('Options', (object,), { 'VERBOSE': True })() 
options.IGNORE_WARNINGS = False 

ध्यान दें कि आप एक प्रारंभिक शब्दकोश प्रदान कर सकते हैं, या बस इसे खाली छोड़ दें।

Options = type('Options', (object,), {}) 
options = Options() 
options.VERBOSE = True 
options.IGNORE_WARNINGS = False 

बहुत पाइथनिक नहीं है।

-2

सरल वस्तु और नाम tuples जाने का रास्ता

+0

क्या आप विस्तारित या उदाहरण दे सकते हैं? – ArtB

संबंधित मुद्दे