Bir değişkenin bir liste veya grup olup olmadığını test etme


234

Python'da, bir değişkenin bir liste veya bir demet içerip içermediğini test etmenin en iyi yolu nedir? (yani bir koleksiyon)

isinstance()Burada önerildiği kadar kötü mü ? http://www.canonical.org/~kragen/isinstance/

Güncelleme: Bir dizeyi bir dizeden ayırmak istememizin en yaygın nedeni, özyinelemeli bir algoritma ile keşfettiğim dizelerin listelerinin listelerinin listelerinin süresiz derin iç içe ağacı / veri yapısı olduğunda ve ihtiyacım var "yaprak" düğümlere çarptığımı bilmek.


72
Kötülük biraz kolay olduğu için geniş çaplı tip denetleme. Dilin bir parçası. Eğer bu kadar kötüyse, birisi onu çıkarmak için bir PEP yazmalıdır.
Adam Crossland

4
@Adam Crossland: "Dilin bir parçası." Tıpkı sıfıra bölme gibi. Önlenebilir. Bu durumda, ek bilgi olmadan, muhtemelen tamamen gereksizdir. Python'da çoğu tür denetimi gereksizdir. Her şey gereksiz olmadığından , bir tür kontrolün olması gerekir. Ancak bu, yararlı, değerli ve hatta iyi bir fikir olduğu anlamına gelmez.
S.Lott

11
Yani bir tür kontrolün gerekli olduğunu söylüyorsunuz, ancak buna rağmen işe yaramaz, değersiz ve kötü bir fikir. Üzgünüm, bu hiç mantıklı değil.
Glenn Maynard

18
"XXX kötüdür" kötü bir şekilde tasarlanmıştır, "XXX yapma isteğinizin gerçekte ne zaman kullanılması gerektiğini anlamadığınızı ve neredeyse kesinlikle başka bir şey istediğinizi" önerir. Büyük olasılıkla burada durum böyle.
Glenn Maynard

2
Onu kötülük olarak reddetmedim. Kötülüğün ne zaman ve haklı olduğu hakkında kısa bir makale yazdım. Bu makale birçok şey olabilir - doğru, yanlış, açık, belirsiz, zevkli, sıkıcı - ama olmayan bir şey tekniğin geniş bir işten çıkarılmasıdır.
Kragen Javier Sitaker

Yanıtlar:


101

Devam edin ve isinstanceihtiyacınız varsa kullanın . Özel dizileri, yinelemeleri ve gerçekten ihtiyaç duyabileceğiniz diğer şeyleri hariç tuttuğundan biraz kötüdür. Bununla birlikte, örneğin birisi bir ip geçirirse bazen farklı davranmanız gerekir. Benim tercihim açıkça kontrol etmek strya da unicodegibi olurdu :

import types
isinstance(var, types.StringTypes)

NB Hata types.StringTypeyapma types.StringTypes. İkincisi birleşir strve unicodenesneler.

typesModülü yerine yukarıdaki kullanmamayı tercih eğer öyleyse, alternatif karşı açıkça kontrol edebilirsiniz, sadece nesnenin tipine karşı doğrudan kontrol lehine eskimiş birçok kişi tarafından kabul edilir strve unicodebu gibi:

isinstance(var, (str, unicode)):

Düzenle:

Daha da iyisi:

isinstance(var, basestring)

Düzenlemeyi bitir

Bunlardan herhangi birinden sonra, normal bir sekans alıyormuş gibi davranmaya geri dönebilir, sekans olmayanların uygun istisnaları artırmasına izin verebilirsiniz.

Tip kontrolüyle ilgili "kötü" şeyin, belirli bir nesne türü için farklı davranmak isteyebileceğiniz değil, işlevinizi yapay olarak, doğru olanı yapacak beklenmedik nesne türleriyle doğru şeyi yapmaktan yapay olarak kısıtlamanıza bakın. Tür denetlenmeyen bir son yedeğiniz varsa, bu kısıtlamayı kaldırırsınız. Çok fazla tür kontrolünün, bazı yeniden düzenleme yapmak isteyebileceğinizi gösteren bir kod kokusu olduğu unutulmamalıdır, ancak bu mutlaka getgo'dan kaçınmanız gerektiği anlamına gelmez.


2
Türler modülü biraz tarihsel bir eserdir. Docs.python.org/dev/library/types.html#module-types'de belirtildiği gibi, gerçekten strtürünü kontrol etmeniz gerekip gerekmediğini, bunun types.StringTypeiçin yalnızca bir takma ad kullanmak yerine doğrudan kullanmanız gerekir. Ama bu cevabın sorulan soruya cevap verdiğini düşünmüyorum, çünkü bu "koleksiyon" ile ilgiliydi. Kontrol etmek için abckullanabileceğiniz bir şey olmayan modüle sahip olacak kadar yeni bir python kullanmıyorsanız isinstanceve o zaman bile mümkün olduğunca kontrolden kaçınmanızı tavsiye ederim.
mzz

1
assert isinstance(u'abc', str) == False. typesModülü kullanmak yerine doğrudan türe karşı kontrol etmenin daha iyi olduğunu kabul ediyorum , ancak olmayan bir types.StringTypesşey stryapıyor: True strve unicodenesneler için True döndürür . Alternatif olarak çift çek sunmak için cevabımı düzenleyeceğim.
jcdyer

1
Doğrudan koleksiyonları kontrol etme sorusuna cevap vermediğimin farkındayım, ancak sorulan asıl soru " isinstanceKötülük mü?" Ve (1) kötü olmayan bir kullanım olduğu için bir karşı örnek verdim isinstance, çünkü bir geri dönüşe sahip olmak ördekleri kırmak anlamına gelmez ve (2) insanların kontrol edip etmemek istedikleri çok yaygın bir motivasyon için iyi bir çözümdür. bir şey bir listveya tuple(yani onları dizelerden ayırmak).
jcdyer

Özel türlerin de dizeler gibi davranmasının yararlı olduğu konusunda uyarıyorum. Ama Python'un
OO'su

Ne class Foo(str): passistiyorsun?
jcdyer

567
if type(x) is list:
    print 'a list'
elif type(x) is tuple:
    print 'a tuple'
else:
    print 'neither a tuple or a list'

1
Çalışmıyor gibi görünüyor: type ([]) ==> list; type ([]) is list ===> Yanlış
sten

3
Python 2.7.5'te: type([]) is listİadeTrue
David Geiger

54
type(x) in [list,tuple]daha kısadır.
Alex Holcombe

x ve type (x)
listeyse

Çok aşağı kaydırmak zorunda kaldım. : D
Rithwik

38

isinstanceGereksiz olduğu sürece kullanmakta yanlış bir şey yoktur . Bir değişkenin yalnızca bir liste / grup olması gerekiyorsa, arayüzü belgeleyin ve sadece bu şekilde kullanın. Aksi takdirde, bir çek tamamen makul olur:

if isinstance(a, collections.Iterable):
    # use as a container
else:
    # not a container!

Çek Bu tip standart dize olduğu gibi bazı iyi kullanım durumları, var startswith / endswith birden fazla yolu var - bunlar bir tanımlama grubu olmadığını görmek için açık çek kullanarak CPython içinde C uygulanmaktadır doğru olması rağmen (yöntemlerden Bu sorunu çözmek için, bağlantı verdiğiniz makalede belirtildiği gibi).

Açık bir denetim, nesneyi bir kapsayıcı olarak kullanmaya ve istisnayı işlemeye çalışmaktan daha iyidir - bu, kodla ilgili her türlü sorunun kısmen veya gereksiz olarak çalıştırılmasına neden olabilir.


15
Bu, bir değişkenin yinelenebilir olup olmadığını kontrol etmenin güzel bir yoludur. Ancak, muhtemelen bu sorunun amaçları için işe yaramayacaktır. Bir dizenin de yinelenebilir olduğu ve muhtemelen yanlış bir pozitif oluşturacağı konusunda bilgilendirilmelidir.
Corey O.Temmuz

Bir setnesne de tekrarlanabilir bir şeydir, bu da ondan elbette öğeleri açabileceğiniz anlamına gelir, ancak belirli bir düzeni garanti etmez, bu da belirli algoritmalar için çok tehlikeli bir şeydir. Elemanların sıralanmasının önemli olduğu durumlarda, bu pasajı kullanan bir algoritma potansiyel olarak farklı çalışmalarda farklı sonuçlar üretebilir!
koo

14

Bağımsız değişkeni bir dizi olması gerektiği gibi belgeleyin ve bir dizi olarak kullanın. Türü kontrol etmeyin.


12

Nasıl hasattr(a, "__iter__")?

Döndürülen nesnenin bir jeneratör olarak tekrarlanıp tekrarlanamayacağını söyler. Varsayılan olarak, tuples ve listeler dize türlerini değil, yapabilir.


bunu gerçekten faydalı buldum.
javadba

8
Ayrıca dizeler için True sonucunu verir (en azından Python 3'te).
SzieberthAdam

2
Bu yanlış cevap. Çünkü 'str' türü de ' iter ' yöntemine sahiptir . @SzieberthAdam haklıydı. 'Set' türü de yinelenebilir, ancak düzenlenemez.
PADYMKO

Ayrıca dikte var __iter__.
thet

Devam ederseniz, herhangi bir özel tür herhangi bir __iter__nedenle olabilir ...
Alexander Irbis

10

Python 2.8 type(list) is listdöndürür false
türünü bu korkunç şekilde karşılaştırma öneririz:

if type(a) == type([]) :
  print "variable a is a list"

(en azından sistemimde, Mac OS X Yosemite'de anaconda kullanarak)


1
Liste (a) türü de yanlış olarak değerlendiriliyor mu?
Dmitriy Sintsov

4
Şunu mu demek istedin Python 2.7.8? python.org/dev/peps/pep-0404/#official-pronouncement
Carl

Merhaba, merak ediyorum: Örneğini neden "korkunç" buluyorsun?
Seth Connell

type(list) is listdöner False, çünkü type(list)olduğunu typedeğil, list. type(list()) is listveya bir listenin başka herhangi bir örneğiyle döner True.
Michael Greene

8

Python "Ördek yazmayı" kullanır, yani değişken bir ördek gibi kwaks ise, o bir ördek olmalı. Sizin durumunuzda, muhtemelen tekrarlanabilir olmasını istersiniz veya öğeye belirli bir dizinden erişmek istersiniz. Sadece bunu yapmalısınız: yani nesneyi bir blok içinde for var:veya var[idx]içinde kullanın ve trybir istisna alırsanız bu bir ördek değildi ...


7
Bu sorun, varmuhtemelen beklenmedik sonuçlarla bir dize yineleme oluşacak olmasıdır.
Brian M. Hunt

Brian M. Hunt tarafından ifade edilen gerçeğe rağmen, izin almaktan ziyade affetme istemek açısından oldukça pitonik bir çözümdür.
Géza Török

6
>>> l = []
>>> l.__class__.__name__ in ('list', 'tuple')
True

3

foo[123]Göstergeyi değişkenle kullanıp kullanamayacağınızı bilmeniz gerekiyorsa, __getitem__(hasattr(foo, '__getitem__')


2

Gerçekten işlev argümanı olarak hemen hemen her şeyi işlemek istiyorsanız daha karmaşık bir test olmalıdır.

type(a) != type('') and hasattr(a, "__iter__")

Bununla birlikte, genellikle bir fonksiyonun tekrarlanabilir olmasını beklemek ve sonra sadece kontrol etmek yeterlidir. type(a) != type('') .

Ayrıca bir dize için basit bir işlem yoluna sahip olabilirsiniz veya güzel olacaksınız ve bir bölünme vb. bir istisna.


2

Bir değişkenin liste veya grup olup olmadığını veya değişken türünü genel olarak kontrol edip etmediğini öğrenmenin başka bir kolay yolu:

    def islist(obj):

        if ("list" in str(type(obj)) ): return True

        else : return False

1

Prensip olarak, yukarıdaki Ignacio ile aynı fikirdeyim, ancak bir şeyin bir demet veya liste olup olmadığını kontrol etmek için türü de kullanabilirsiniz .

>>> a = (1,)
>>> type(a)
(type 'tuple')
>>> a = [1]
>>> type(a)
(type 'list')
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.