개발/Python

[파이썬] 변수가 배열인지 스칼라인지 식별하는 방법

MinorMan 2023. 1. 20. 13:04
반응형

<질문>

인수를 취하는 함수가 있습니다.NBins. 스칼라를 사용하여 이 함수를 호출하고 싶습니다.50또는 배열[0, 10, 20, 30]. 함수 내에서 어떻게 식별할 수 있습니까?NBins이다? 아니면 다르게 말하면 스칼라인지 벡터인지?

나는 이것을 시도했다 :

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

보시다시피 신청할 수 없습니다len에게P, 배열이 아니기 때문에 .... 같은 것이 있습니까?isarray또는isscalar파이썬에서?

감사해요


<답변1>

>>> import collections.abc
>>> isinstance([0, 10, 20, 30], collections.abc.Sequence)
True
>>> isinstance(50, collections.abc.Sequence)
False

노트:isinstance클래스의 튜플도 지원합니다.type(x) in (..., ...)피해야 하며 불필요합니다.

확인하고 싶을 수도 있습니다.not isinstance(x, (str, unicode))

에 의해 언급된 바와 같이@2080그리고 또한here이것은 작동하지 않습니다numpy배열. 예.

>>> import collections.abc
>>> import numpy as np
>>> isinstance((1, 2, 3), collections.abc.Sequence)
True
>>> isinstance(np.array([1, 2, 3]), collections.abc.Sequence)
False

어떤 경우에 당신은 대답을 시도 할 수 있습니다@jpaddison3:

>>> hasattr(np.array([1, 2, 3]), "__len__")
True
>>> hasattr([1, 2, 3], "__len__")
True
>>> hasattr((1, 2, 3), "__len__")
True

그러나 언급한 바와 같이here, 이것도 완벽하지 않으며 (적어도 나에 따르면) 사전을 시퀀스로 잘못 분류하는 반면isinstance~와 함께collections.abc.Sequence올바르게 분류:

>>> hasattr({"a": 1}, "__len__")
True
>>> from numpy.distutils.misc_util import is_sequence
>>> is_sequence({"a": 1})
True
>>> isinstance({"a": 1}, collections.abc.Sequence)
False

솔루션을 이와 같이 사용자 지정하고 더 많은 유형을 추가할 수 있습니다.isinstance필요에 따라:

>>> isinstance(np.array([1, 2, 3]), (collections.abc.Sequence, np.ndarray))
True
>>> isinstance([1, 2, 3], (collections.abc.Sequence, np.ndarray))
True

<답변2>

이전 답변은 배열이 파이썬 표준 목록이라고 가정합니다. numpy를 자주 사용하는 사람으로서 다음과 같은 매우 파이썬적인 테스트를 권장합니다.

if hasattr(N, "__len__")

<답변3>

@jamylak과 @jpaddison3의 답변을 결합하여 입력으로 numpy 배열에 대해 강력하고 목록과 동일한 방식으로 처리해야 하는 경우 다음을 사용해야 합니다.

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

이는 목록, 튜플 및 numpy 배열의 하위 클래스에 대해 강력합니다.

그리고 시퀀스의 다른 모든 하위 클래스(목록과 튜플뿐만 아니라)에 대해서도 강력하게 하려면 다음을 사용하십시오.

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)

>>> 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동일한 방법으로.


<답변4>

numpy에 isscalar()와 동등한 기능이 있습니까? 예.

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

<답변5>

@jamylak의 접근 방식이 더 나은 반면 다음은 대안 접근 방식입니다.

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

<답변6>

다른 대체 접근 방식(클래스 사용이름속성):

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

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

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

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

아무 것도 가져올 필요가 없습니다.


<답변7>

내가 찾은 가장 좋은 방법은 다음과 같습니다.__len__그리고__getitem__.

왜 그런지 물어볼 수 있습니까? 이유는 다음과 같습니다.

  1. 대중적인 방법isinstance(obj, abc.Sequence)구현하지 않기 때문에 PyTorch의 Tensor를 포함한 일부 개체에서 실패합니다.__contains__.
  2. 불행히도 Python의 collections.abc에는 다음 항목만 확인하는 항목이 없습니다.__len__그리고__getitem__배열과 같은 객체에 대한 최소한의 방법이라고 생각합니다.
  3. 목록, 튜플, ndarray, Tensor 등에서 작동합니다.

따라서 더 이상 고민하지 않고:

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

대부분의 경우 문자열을 배열이 아닌 값으로 간주하기를 원할 수 있으므로 기본 매개변수를 추가했습니다. 튜플도 마찬가지입니다.


<답변8>

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

<답변9>

제목의 질문에 답하기 위해 변수가 스칼라인지 확인하는 직접적인 방법은 변수를 float로 변환하는 것입니다. 당신이 얻을 경우TypeError, 그렇지 않습니다.

N = [1, 2, 3]
try:
    float(N)
except TypeError:
    print('it is not a scalar')
else:
    print('it is a scalar')

<답변10>

변수의 데이터 타입을 확인할 수 있습니다.

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

P의 데이터 유형으로 출력됩니다.


정수인지 배열인지 구분할 수 있습니다.


<답변11>

나는 그러한 기본적인 질문에 파이썬에서 즉각적인 대답이 없는 것 같다는 것에 놀랐습니다. 거의 모든 제안 된 답변은 일종의 유형 검사를 사용하는 것 같습니다. 일반적으로 파이썬에서는 권장되지 않으며 특정 사례로 제한되는 것 같습니다 (튜플 또는 목록이 아닌 다른 숫자 유형 또는 일반 반복 가능 개체에서는 실패 함).

나에게 더 잘 작동하는 것은 numpy를 가져오고 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)
 in ()
----> 1 len(np.array(a))

TypeError: len() of unsized object

<답변12>

간단히 사용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

<답변13>

Python의 일반적인 지침은 허가보다는 용서를 요청하는 것이므로 시퀀스에서 문자열/스칼라를 감지하는 가장 파이썬적인 방법은 정수가 포함되어 있는지 확인하는 것입니다.

try:
    1 in a
    print('{} is a sequence'.format(a))
except TypeError:
    print('{} is a scalar or string'.format(a))

<답변14>

preds_test[0] is of shape (128,128,1) isinstance() 함수를 사용하여 데이터 유형을 확인합니다. isinstance는 2개의 인수를 사용합니다. 첫 번째 인수는 데이터입니다. 두 번째 인수는 데이터 유형 isinstance(preds_test[0], np.ndarray)가 출력을 True로 제공합니다. 이는 preds_test[0]가 배열임을 의미합니다.

반응형