2013-04-24 5 views
5

मुझे एक ऐसा फ़ंक्शन चाहिए जो आम तौर पर टाइप एक्स के तर्क में होता है जहां एक्स या तो स्केलर, एक सूची या एक टोक होता है, और अन्य जानकारी के आधार पर एक्स की एक ही कुंजी मानों की एक सूची देता है।पाइथन में स्केलर, सूची और निर्देश तर्कों के बीच अंतर करने का सबसे अच्छा तरीका?

def foo(info, k): 
    return [bar(item,k) for item in processInfo(info)] 

def bar(item, keydata): 
    # pseudocode follows. 
    # What we want to do is return an output of parallel type to the input key k, 
    # using the key data to lookup information from the input item. 
    if keydata is a scalar: 
     return item[keydata] 
    elif keydata is a list: 
     return [item[k] for k in keydata] 
    elif keydata is a dict: 
     return dict((k,item[v]) for (k,v) in keydata.iteritems()) 
    else: 
     raise ValueError('bar expects a scalar, list, or dict') 

मेरा सवाल है, मैं तीन प्रकार के बीच कैसे प्रेषित कर सकता हूं?


संपादित करें: एक स्ट्रिंग को स्केलर के रूप में व्याख्या किया जाना चाहिए, सूची/पुनरावर्तनीय नहीं। ट्यूपल्स को पुनरावृत्त के रूप में व्याख्या किया जाना है।

संपादित 2: मुझे बतख टाइपिंग चाहिए, सख्त टाइपिंग नहीं।

+1

क्या होगा अगर कोई वस्तु किसी सूची और एक निर्देश के व्यवहार को प्रदर्शित कर सके? – Meitham

+1

तब ताना-जैसे वस्तुओं के लिए व्यवहार को पुन: प्रयोज्य वस्तुओं के लिए व्यवहार पर प्राथमिकता दी जाती है –

+0

इस प्रश्न को नामकरण की आवश्यकता है, क्योंकि यह शीर्षक और सूची के बीच अंतर निर्धारित करने के लिए सबसे अच्छा है, न कि स्केलर और नॉनस्कालर के बीच, शीर्षक का तात्पर्य है। मैं खोजों में इसे छोड़कर रखता हूं। – SystemParadox

उत्तर

3

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

संपादित: स्ट्रिंग्स के लिए विशेष मामला जोड़ा

if isinstance(keydata, basestring): 
    # special case to avoid considering strings as containers 
    # for python 3.x use str instead of basestring 
    return item[keydata] 
try: 
    return dict((k,item[v]) for (k,v) in keydata.iteritems()) 
except AttributeError: 
    # it's not a dict-like 
    pass 
try: 
    return [item[k] for k in keydata] 
except TypeError: 
    # it's not iterable 
return item[keydata] 

नियंत्रण प्रवाह की पसंद कैसे लचीला आप होना चाहते हैं पर निर्भर करता है, और यह भी कि कैसे आप अस्पष्ट साथ यो सौदा चाहते हैं मामलों। उदाहरण के लिए, एक स्ट्रिंग वर्णों या एक स्केलर का अनुक्रम माना जाता है?

+0

प्रश्न में मेरे संपादन देखें। स्ट्रिंग एक स्केलर है। (मेरे उद्देश्यों के लिए) –

+0

क्या यह विशेष-केस स्ट्रिंग्स (और यूनिकोड्स, मुझे लगता है!) के लिए स्वीकार्य होगा और बाकी सबकुछ बतख-टाइप किया जाएगा? अन्यथा आपको अधिक विस्तार से निर्दिष्ट करने की आवश्यकता है कि वास्तव में तारों को इतना खास बनाता है :-) – Felipe

+0

हाँ ... यह विशेष-केस स्ट्रिंग के लिए ठीक है। स्ट्रिंग्स स्ट्रिंग्स हैं। :-) –

0
if isinstance(keydata,(int,float,str)): #scalar 

elif isinstance(keydata,(list,tuple)):#iterable 

elif isinstance(keydata,dict):#dictionary 

शायद ??

+3

'str' एक दिलचस्प मामला है, यह एक स्केलर और एक पुनरावर्तनीय दोनों के रूप में कार्य कर सकता है। –

+0

हाँ ... लेकिन मुझे लगा कि यह ओपी की जरूरतों के लिए एक स्केलर के करीब था ... –

+0

ओह बकवास, जो जीवन को और अधिक कठिन बनाता है, क्योंकि मैं एक स्ट्रिंग के रूप में एक स्ट्रिंग के रूप में इलाज करना चाहता हूं, एक पुनरावृत्ति के रूप में नहीं। –

2

(आईएम शायद कुछ प्रकार के लापता) ... आयात संग्रह से नई फैंसी सामान :) का उपयोग करें

>>> isinstance([], collections.Sequence) 
True 
>>> isinstance({}, collections.Mapping) 
True 

तुम भी types मॉड्यूल को देख पर विचार करना चाहिए

+1

'इंस्टेंसेंस ('' संग्रह। सिक्योरेंस) 'भी' True' है। –

+0

@MartijnPieters यह नहीं होना चाहिए :) मैं यह भी कहूंगा कि एक ट्यूपल एक स्केलर है क्योंकि यह हैशबल है :) – Meitham

+0

मैं उन्हें स्केलर्स नहीं कहूंगा क्योंकि वे हैंशबल हैं लेकिन क्योंकि वे अपरिवर्तनीय हैं, लेकिन हाँ। –

5

आप के बाद से str और dict प्रकार iterable हैं उचित क्रम में काम करने होंगे के अनुसार सिफारिश की है।

from collections import Iterable, Mapping # in Python 3 use from collections.abc 

def bar(item, keydata): 
    if isinstance(keydata, Mapping): 
     return {k: item[v] for (k,v) in keydata.iteritems()} 
    elif isinstance(keydata, Iterable) and not isinstance(keydata, str): 
     return [item[k] for k in keydata] 
    return item[keydata] 
0

सभी जानकारी के लिए धन्यवाद!

मैं यह कर समाप्त हो गया, के बाद से मैं के कुछ पूर्व प्रसंस्करण करना था keydata जानकारी पर पुनरावृत्ति करने से पहले:

def asKVlists(keydata): 
    # return a tuple (keys, values, isScalar) 
    # where keys and values are iterable 
    if not isinstance(keydata, basestring): 
     # check for dict behavior: 
     try: 
      return zip(*keydata.iteritems()) + [False] 
     except AttributeError: 
      pass 

     # otherwise check for list behavior 
     # make sure we can iterate over it 
     try: 
      iter(keydata) 
      return (None, keydata, False) 
     except TypeError: 
      pass 
    return (None, (keydata,), True) 
0
def is_scalar(x): 
    return hasattr(x, 'lower') or not hasattr(x, '__iter__') 

तो फिर तुम किसी की वजह से एक isinstance में नाकाम रहने के बारे में चिंता करने की आवश्यकता नहीं है अप्रत्याशित कुछ से उपनिवेशित एक पुनरावर्तनीय कार्यान्वयन।

+1

लेकिन फिर मुझे किसी को 'निचले()' विशेषता या विधि के साथ एक पुनरावर्तक लागू करने के बारे में चिंता करने की ज़रूरत है। –

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