2014-09-23 10 views
7

मैं एक एपीआई में स्वत: स्ट्रिंग स्वरूपण प्रदान करना चाहते हैं ऐसी है कि:मैं पाइथन प्रारूप स्ट्रिंग से कीवर्ड कैसे निकाल सकता हूं?

my_api("path/to/{self.category}/{self.name}", ...) 

विशेषताओं स्वरूपण स्ट्रिंग में बाहर बुलाया के मूल्यों के साथ बदला जा सकता है।


कैसे मैं एक अजगर प्रारूप स्ट्रिंग से कीवर्ड तर्क निकालने करते हैं:

"non-keyword {keyword1} {{escaped brackets}} {} {keyword2}" => 'keyword1', 'keyword2' 
+0

मुझे लगता है कि आप प्रारूप का उपयोग नहीं करना चाहते हैं? – user189

+0

@ user189 I ** ** ' का उपयोग करेगा .format (** kwargs)'। मेरा सवाल है कि 'kwargs' शब्दकोश स्वचालित रूप से बनाने के बारे में है। –

उत्तर

27

आप string.Formatter() class उपयोग कर सकते हैं एक स्ट्रिंग में फ़ील्ड पार्स करने के लिए, Formatter.parse() method साथ:

from string import Formatter 

fieldnames = [fname for _, fname, _, _ in Formatter().parse(yourstring) if fname] 

डेमो:

>>> from string import Formatter 
>>> yourstring = "path/to/{self.category}/{self.name}" 
>>> [fname for _, fname, _, _ in Formatter().parse(yourstring) if fname] 
['self.category', 'self.name'] 
>>> yourstring = "non-keyword {keyword1} {{escaped brackets}} {} {keyword2}" 
>>> [fname for _, fname, _, _ in Formatter().parse(yourstring) if fname] 
['keyword1', 'keyword2'] 

आप उन फ़ील्ड नामों को और आगे पार्स कर सकते हैं; इसके लिए आप str._formatter_field_name_split() विधि (पायथन 2)/_string.formatter_field_name_split() फ़ंक्शन (पायथन 3) का उपयोग कर सकते हैं (यह आंतरिक कार्यान्वयन विवरण अन्यथा खुलासा नहीं है; Formatter.get_field() इसे आंतरिक रूप से उपयोग करता है)। यह फ़ंक्शन नाम का पहला भाग देता है, जिसे str.format() पर दिए गए तर्कों में देखा जाएगा, साथ ही शेष फ़ील्ड के लिए जेनरेटर भी होगा।

जनरेटर (is_attribute, name) tuples पैदा करता है; is_attribute सच अगर अगले नाम एक विशेषता के रूप में इलाज किया जा रहा है, गलत है अगर यह obj[name] के साथ देखने के लिए एक आइटम है:

try: 
    # Python 3 
    from _string import formatter_field_name_split 
except ImportError: 
    formatter_field_name_split = str._formatter_field_name_split 
from string import Formatter 

field_references = {formatter_field_name_split(fname)[0] 
for _, fname, _, _ in Formatter().parse(yourstring) if fname} 

डेमो:

>>> from string import Formatter 
>>> from _string import formatter_field_name_split 
>>> yourstring = "path/to/{self.category}/{self.name}" 
>>> {formatter_field_name_split(fname)[0] 
... for _, fname, _, _ in Formatter().parse(yourstring) if fname} 
{'self'} 

को ध्यान में रखें इस समारोह है कि Formatter() वर्ग के आंतरिक कार्यान्वयन विवरण का हिस्सा और बिना किसी सूचना के पाइथन से बदला या हटाया जा सकता है, और अन्य पायथन कार्यान्वयन में भी उपलब्ध नहीं हो सकता है।

+0

बस उत्सुक, मार्टिजन, क्या आप * नई स्ट्रिंग उत्पन्न करने के लिए एक साधारण str.replace() या re.sub() (या पूरी तरह से कुछ अलग) का उपयोग करेंगे? – mtik00

+0

@ mtik00: उपयोग के मामले पर निर्भर करता है; कभी-कभी 'str.replace()' केवल यही कहा जाता है। –

+0

आपके इनपुट के लिए धन्यवाद! इस विशिष्ट मामले में, मैंने लूप में 'str.replace() 'का उपयोग किया होगा; अच्छा और सरल – mtik00

0

आप "path/to/{self.category}/{self.name}".format(self=self) कर सकते हैं। इस प्रकार आप __getattr__ में उन kwargs के साथ काम कर सकते हैं।

+0

के लिए फ़ॉर्मेटिंग जानकारी या रूपांतरण फ़ंक्शन नाम देने या प्रदान करने के लिए कोई फ़ील्ड नहीं है। मुझे नहीं लगता कि यह वास्तव में होगा। –

+0

आपको नहीं लगता कि यह वास्तव में क्या होगा? – pacholik

+0

@JaceBrowning: यह काम करेगा; ' स्वयं .__ getattr__' को 'self' पर प्रत्येक विशेषता के लिए बुलाया जाएगा। हालांकि, यह किसी भी चीज की सहायता नहीं करता है जो' self' पर विशेषता नहीं है। –

3

यदि सभी प्लेसहोल्डर्स का नाम दिया गया है, तो एक विशेष शब्दकोश का उपयोग इस बात को रोकने के लिए किया जा सकता है कि किन कुंजीों को एक्सेस करने और सरणी में लॉग इन करने का प्रयास किया जाता है।

def format_keys(str_): 
    class HelperDict(dict): 
     def __init__(self): 
      self._keys = [] 
     def __getitem__(self, key): 
      self._keys.append(key)  
    d = HelperDict() 
    str_.format_map(d) 
    return d._keys 

ध्यान दें कि अगर वहाँ अनाम प्लेसहोल्डर हैं, एक IndexError (सीमा से बाहर टपल इंडेक्स) .format() द्वारा बढ़ा दी जाएगी।

+0

एक मजेदार विचार है लेकिन इसे कुछ पॉलिश की आवश्यकता है। उदाहरण के लिए '__getitem__' द्वारा लौटाई गई 'कोई भी' प्रारूप स्ट्रिंग ली से अनचाहे अपवाद का कारण बन जाएगी के '' मेरा {foo} {bar: 03d} ''है। – wim

1

Martijn के जवाब बंद बिल्डिंग, कि मैं का उपयोग किया है व्यापक सूची के लिए एक आसान प्रारूप है:

>>> yourstring = "path/to/{self.category}/{self.name}" 
>>> [x[1] for x in yourstring._formatter_parser() if x[1]] 
['self.category', 'self.name'] 

यह कार्यात्मक रूप बिल्कुल एक ही बस इतना आसान पचाने के लिए है,।

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