अजगर: कैसे पहचानें कि एक चर एक सरणी या एक अदिश राशि है


283

मेरे पास एक फ़ंक्शन है जो तर्क लेता है NBins। मैं इस फ़ंक्शन को स्केलर 50या सरणी के साथ कॉल करना चाहता हूं [0, 10, 20, 30]। मैं फ़ंक्शन के भीतर कैसे पहचान सकता हूं, लंबाई क्या NBinsहै? या अलग ढंग से कहा, अगर यह एक अदिश या सदिश राशि है?

मैंने यह कोशिश की:

>>> N=[2,3,5]
>>> P = 5
>>> len(N)
3
>>> len(P)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()
>>> 

जैसा कि आप देख, मैं लागू नहीं कर सकते lenकरने के लिए P, यह एक सरणी नहीं है के बाद से .... की तरह वहाँ कुछ है isarrayया isscalarअजगर में?

धन्यवाद


3
क्या आपने इसके लिए परीक्षण करने की कोशिश की है type?
सुकृत कालरा

जवाबों:


390
>>> isinstance([0, 10, 20, 30], list)
True
>>> isinstance(50, list)
False

किसी भी प्रकार के अनुक्रम का समर्थन करने के लिए, collections.Sequenceइसके बजाय जांचें list

नोट : isinstanceकक्षाओं के टपल का भी समर्थन करता है, चेक type(x) in (..., ...)से बचा जाना चाहिए और अनावश्यक है।

आप जांच भी कर सकते हैं not isinstance(x, (str, unicode))


3
धन्यवाद, मैंने list
स्केलर्स के

3
हालांकि यह एक महान जवाब है, collections.Sequenceस्ट्रिंग के लिए भी एबीसी है, इसलिए इसे ध्यान में रखा जाना चाहिए। मैं कुछ का उपयोग कर रहा हूँ if type(x) is not str and isinstance(x, collections.Sequence):। यह बहुत अच्छा नहीं है, लेकिन यह विश्वसनीय है।
bbenne10

2
@ bbenne10 यकीन है, लेकिन बचने के लिए type, और यह भी not isinstance(x, (str, unicode))अजगर 2 पर जाँच
11

आपने क्यों कहा "चेक प्रकार (x) में (..., ...) से बचा जाना चाहिए और अनावश्यक है।" यदि आप ऐसा कहते हैं, तो यह समझाने के लिए बहुत दयालु होगा कि, शायद मैं यह आश्चर्यचकित करने वाला एकमात्र व्यक्ति नहीं हूं कि इसे क्यों टाला जाए।
ओलिवियर पोंस


119

पिछले उत्तर मान लेते हैं कि सरणी एक पायथन मानक सूची है। कोई है जो अक्सर खस्ता उपयोग करता है के रूप में, मैं एक बहुत pythonic परीक्षण की सिफारिश करेंगे:

if hasattr(N, "__len__")

12
तार एक __len__विशेषता है (इसलिए मुझे लगता है, तकनीकी रूप से एक अदिश प्रकार नहीं)
xofer

20
if hasattr(N, '__len__') and (not isinstance(N, str))स्ट्रिंग्स के लिए ठीक से खाता होगा।
Thucydides411

1
इसके अलावा अजगर 3 पर dict के लिए खाते
ब्रूनो हेनरिक

44

@Jamylak और @ jpaddison3 के उत्तरों को एक साथ मिलाकर, यदि आपको इनपुट के रूप में संख्यात्मक सरणियों के खिलाफ मजबूत होना है और उन्हें सूचियों की तरह से संभालना है, तो आपको उपयोग करना चाहिए

import numpy as np
isinstance(P, (list, tuple, np.ndarray))

यह सूची, टपल और सुन्न सरणियों के उपवर्गों के खिलाफ मजबूत है।

और यदि आप अनुक्रम के अन्य सभी उपवर्गों के खिलाफ मजबूत होना चाहते हैं (न कि केवल सूची और तुच्छ), का उपयोग करें

import collections
import numpy as np
isinstance(P, (collections.Sequence, np.ndarray))

आपको इस तरह से चीजों को क्यों करना चाहिए isinstanceऔर type(P)लक्ष्य मूल्य के साथ तुलना नहीं करनी चाहिए ? यहां एक उदाहरण है, जहां हम NewListसूची के एक तुच्छ उपवर्ग का व्यवहार बनाते हैं और उसका अध्ययन करते हैं ।

>>> class NewList(list):
...     isThisAList = '???'
... 
>>> x = NewList([0,1])
>>> y = list([0,1])
>>> print x
[0, 1]
>>> print y
[0, 1]
>>> x==y
True
>>> type(x)
<class '__main__.NewList'>
>>> type(x) is list
False
>>> type(y) is list
True
>>> type(x).__name__
'NewList'
>>> isinstance(x, list)
True

बराबर होने xऔर yतुलना करने के बावजूद , उन्हें संभालने typeसे अलग व्यवहार होगा। हालाँकि, चूंकि xएक उपवर्ग का एक उदाहरण है list, का उपयोग isinstance(x,list)करना वांछित व्यवहार और व्यवहार xऔर yउसी तरीके से देता है।


यह वह उत्तर है जो मेरी आवश्यकताओं के अनुकूल है। मैंने अभी सेट भी जोड़ा है। क्योंकि मैं dicts के खिलाफ मजबूत नहीं होना चाहता। isinstance(P, (list, tuple, set, np.ndarray))
सैंटियागो

32

क्या खसखस ​​में इस्लेकार () के बराबर है? हाँ।

>>> np.isscalar(3.1)
True
>>> np.isscalar([3.1])
False
>>> np.isscalar(False)
True

6
यह बेहतर और एक उदाहरण होगा: >>> np.isscalar('abcd')रिटर्न True
सिरिटिस मेजर

धन्यवाद! यह उपरोक्त किसी भी से अधिक सामान्य उदाहरण है और इसे प्राथमिकता दी जानी चाहिए। यह ओपी के सवाल का सीधा जवाब भी है।
क्रिस्टोबल सिफोन

1
अच्छा लगा। यद्यपि एक गोत्र यह है कि इस्कल्कर (कोई नहीं) फाल्स लौटाता है। नेम्पी इसे लागू करती हैreturn (isinstance(num, generic) or type(num) in ScalarType or isinstance(num, numbers.Number))
शीतल शाह

5
नहीं, दुख की बात है। यह numpy.isscalar()फ़ंक्शन कई अपरिवर्तनीय डिज़ाइन दोषों को पीड़ित करता है और संभवतः भविष्य के कुछ संशोधन में पदावनत किया जाएगा । व्याख्या करने के लिए आधिकारिक दस्तावेज : "लगभग सभी मामलों में np.ndim(x) == 0के बजाय इस्तेमाल किया जाना चाहिए np.isscaler(x), पूर्व भी सही ढंग से 0 दिन सरणियों के लिए सच वापस आ जाएगी के रूप में।" इस तरह से एक मजबूत फॉरवर्ड-कम्पेटिबल विकल्प को numpy.isscalar()तुच्छता से लपेटा जा सकता है numpy.ndim(): जैसे,def is_scalar(obj): return np.ndim(obj) == 0
सेसिल करी

वास्तव में इसे अपवित्र नहीं किया जाना चाहिए क्योंकि np.isscalarयह भ्रामक है। आधिकारिक डॉक ने np.array.ndimहर जगह का उपयोग करने का सुझाव दिया , अर्थात np.isscalar(np.array(12))गलत है जबकि इसे स्केलर के रूप में माना जाना चाहिए np.array(12).ndim0.
knh190

17

जबकि, @ जामिलक का दृष्टिकोण बेहतर है, यहाँ एक वैकल्पिक दृष्टिकोण है

>>> N=[2,3,5]
>>> P = 5
>>> type(P) in (tuple, list)
False
>>> type(N) in (tuple, list)
True

2
यह बहुत अच्छा होता अगर जवाब देने वाले ने जवाब भी दिया होता।
सुकृत कालरा

मैंने वास्तव में उत्थान किया है, लेकिन फिर महसूस किया कि यह 2.7 में काम नहीं कर रहा है: >>> p = [] >>> प्रकार (पी) में (सूची) ट्रेसबैक (सबसे हालिया कॉल अंतिम): फ़ाइल "<stdin>" , लाइन 1, में <मॉड्यूल>
ओलेग ग्रैब

@ ऑयलग्रेब: कोशिश करो type(p) in (list, )
सुकृत कालरा

आह, यह दाईं ओर एक टुप है, सूची नहीं है, इसे मिला, धन्यवाद और यह अब काम करता है। मुझे अफसोस है, मैं 2 बार
उत्थान

3

एक अन्य वैकल्पिक दृष्टिकोण (वर्ग नाम संपत्ति का उपयोग ):

N = [2,3,5]
P = 5

type(N).__name__ == 'list'
True

type(P).__name__ == 'int'
True

type(N).__name__ in ('list', 'tuple')
True

कुछ भी आयात करने की आवश्यकता नहीं है।


3

यहाँ सबसे अच्छा तरीका मुझे मिला है: के अस्तित्व की जाँच करें __len__और __getitem__

आप पूछ सकते हैं क्यों? कारणों में शामिल हैं:

  1. लोकप्रिय विधि isinstance(obj, abc.Sequence)PyTorch के Tensor सहित कुछ वस्तुओं पर विफल हो जाती है क्योंकि वे लागू नहीं होते हैं __contains__
  2. दुर्भाग्य से, पायथन के संग्रह में कुछ भी नहीं है। केवल उस चीज़ की जाँच करता है __len__और __getitem__जो मुझे लगता है कि सरणी जैसी वस्तुओं के लिए न्यूनतम तरीके हैं।
  3. यह लिस्ट, टपल, नडर्रे, टेन्सर आदि पर काम करता है।

तो आगे की हलचल के बिना:

def is_array_like(obj, string_is_array=False, tuple_is_array=True):
    result = hasattr(obj, "__len__") and hasattr(obj, '__getitem__') 
    if result and not string_is_array and isinstance(obj, (str, abc.ByteString)):
        result = False
    if result and not tuple_is_array and isinstance(obj, tuple):
        result = False
    return result

ध्यान दें कि मैंने डिफ़ॉल्ट पैरामीटर जोड़ा है क्योंकि अधिकांश समय आप स्ट्रिंग्स को मान के रूप में मान सकते हैं, न कि सरणियाँ। इसी तरह टुपल्स के लिए।


2
>>> N=[2,3,5]
>>> P = 5
>>> type(P)==type(0)
True
>>> type([1,2])==type(N)
True
>>> type(P)==type([1,2])
False

2

आप डेटा प्रकार के चर की जांच कर सकते हैं।

N = [2,3,5]
P = 5
type(P)

यह आपको पी के डेटा प्रकार के रूप में पुट आउट देगा।

<type 'int'>

ताकि आप अंतर कर सकें कि यह एक पूर्णांक या एक सरणी है।


2

मुझे आश्चर्य है कि इस तरह के मूल प्रश्न का अजगर में तत्काल उत्तर नहीं लगता है। मुझे ऐसा लगता है कि लगभग सभी प्रस्तावित उत्तर कुछ प्रकार की जाँच का उपयोग करते हैं, जो आमतौर पर अजगर में सलाह नहीं दी जाती है और वे एक विशिष्ट मामले तक ही सीमित लगते हैं (वे अलग-अलग संख्यात्मक प्रकार या सामान्य चलने योग्य वस्तुओं के साथ विफल होते हैं जो ट्यूपल्स या सूची नहीं हैं)।

मेरे लिए, जो बेहतर काम करता है वह सुपाच्य है और array.size का उपयोग करता है, उदाहरण के लिए:

>>> a=1
>>> np.array(a)
Out[1]: array(1)

>>> np.array(a).size
Out[2]: 1

>>> np.array([1,2]).size
Out[3]: 2

>>> np.array('125')
Out[4]: 1

नोट भी:

>>> len(np.array([1,2]))

Out[5]: 2

परंतु:

>>> len(np.array(a))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-40-f5055b93f729> in <module>()
----> 1 len(np.array(a))

TypeError: len() of unsized object

मुझे यह भी आश्चर्य है कि उनमें से कोई भी जनरेटर के साथ व्यवहार नहीं करता है।
RhysC

2

sizeइसके बजाय बस का उपयोग करें len!

>>> from numpy import size
>>> N = [2, 3, 5]
>>> size(N)
3
>>> N = array([2, 3, 5])
>>> size(N)
3
>>> P = 5
>>> size(P)
1

2
NameError: नाम 'आकार' परिभाषित नहीं है
थांग

1
यह सच है। मैं इसे नोट किए बिना संख्यात्मक आकार का उपयोग कर रहा था। आपको आवश्यकता है: सुन्न आयात आकार से
मैथ्यू विल्लिन

2
np.size(5)और np.size([5])दोनों == हैं 1, इसलिए यह सही प्रकार से भेद नहीं करता है (यानी, एक स्केलर की पहचान करें), जो मुझे लगता है कि लक्ष्य है।
माइकल

यह एक दिलचस्प टिप्पणी है। मूल प्रश्न isscalar को संदर्भित करता है, जो एक मैटलैब फ़ंक्शन है। मतलाब में, एक स्केलर और आकार 1 के बीच कोई अंतर नहीं है, यह एक वेक्टर या एन-मंद सरणी हो सकता है। IMHO, यह Matlab के लिए एक प्लस है।
मैथ्यू विलेन

0

preds_test [0] आकार का है (128,128,1) आइंस्टीन () फ़ंक्शन का उपयोग कर अपने डेटा प्रकार की जांच करते हैं आइंस्टीन 2 तर्क लेता है। 1 तर्क डेटा है 2 तर्क डेटा प्रकार isinstance है (preds_test [0], np.ndarray) आउटपुट को True देता है। इसका मतलब है कि preds_test [0] एक सरणी है।


0

शीर्षक में प्रश्न का उत्तर देने के लिए, यह बताने का एक सीधा तरीका है कि क्या एक चर एक अदिश राशि है जो इसे एक फ्लोट में बदलने की कोशिश करता है। यदि आपको मिलता है TypeError, तो यह नहीं है।

N = [1, 2, 3]
try:
    float(N)
except TypeError:
    print('it is not a scalar')
else:
    print('it is a scalar')
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.