Satırına benzer bir kodla karşılaştım
x[x<2]=0
Varyasyonlarla uğraşırken, hala bu sözdiziminin ne yaptığına bağlı kaldım.
Örnekler:
>>> x = [1,2,3,4,5]
>>> x[x<2]
1
>>> x[x<3]
1
>>> x[x>2]
2
>>> x[x<2]=0
>>> x
[0, 2, 3, 4, 5]
Satırına benzer bir kodla karşılaştım
x[x<2]=0
Varyasyonlarla uğraşırken, hala bu sözdiziminin ne yaptığına bağlı kaldım.
Örnekler:
>>> x = [1,2,3,4,5]
>>> x[x<2]
1
>>> x[x<3]
1
>>> x[x>2]
2
>>> x[x<2]=0
>>> x
[0, 2, 3, 4, 5]
TypeError: unorderable types: list() < int()
.
Yanıtlar:
Bu sadece NumPy dizileriyle mantıklıdır . Listelerle ilgili davranış işe yaramaz ve Python 2'ye özgüdür (Python 3'e değil). Orijinal nesnenin gerçekten bir NumPy dizisi olup olmadığını (aşağıya bakınız) ve bir liste olmadığını iki kez kontrol etmek isteyebilirsiniz.
Ancak buradaki kodunuzda, x basit bir listedir.
Dan beri
x < 2
False yani 0, dolayısıyla
x[x<2]
dır-dir x[0]
x[0]
değişiyor.
Tersine, x[x>2]
bir x[True]
veyax[1]
Yani x[1]
değişiyor.
Bu neden oluyor?
Karşılaştırma kuralları:
İki dizi veya iki sayısal tür sipariş ettiğinizde, sıralama beklenen şekilde yapılır (dizge için sözlüksel sıralama, tam sayılar için sayısal sıralama).
Sayısal ve sayısal olmayan bir tür sipariş ettiğinizde, sayısal tür önce gelir.
İkisinin de sayısal olmadığı iki uyumsuz türü sipariş ettiğinizde, tür adlarının alfabetik sırasına göre sıralanırlar:
Yani aşağıdaki siparişimiz var
sayısal <liste <dize <tuple
Python string ve int'i nasıl karşılaştırır? Sorusunun kabul edilen cevabına bakın. .
Eğer x bir NumPy dizisiyse , sözdizimi boolean dizi indekslemesi nedeniyle daha anlamlıdır . Bu durumda, x < 2
hiç de boole değildir; bu her bir elemanı olup temsil Boolean bir dizi var x
az 2. fazla oldu x[x < 2] = 0
sonra unsurları seçer x
bu 2 den aşağı ve 0 görmek için bu hücreleri harekete Endeksleme .
>>> x = np.array([1., -1., -2., 3])
>>> x < 0
array([False, True, True, False], dtype=bool)
>>> x[x < 0] += 20 # All elements < 0 get increased by 20
>>> x
array([ 1., 19., 18., 3.]) # Only elements < 0 are affected
import
uyuşuk göreceğim .
[0 if i < 2 else i for i in x]
.) Yoksa bu Numpy'de teşvik edilen tarz mı?
x[x<2]
uyuşmuş bir dizi [0 if i<2 else i for i in x]
döndürürken bir liste döndürür. Bunun nedeni x[x<2]
, bir indeksleme işlemidir (numpy / scipy / pandas'ta verileri maskeleme yeteneği nedeniyle bir dilimleme işlemi olarak anılır), oysa liste kavrama yeni bir nesne tanımıdır. NumPy indekslemesine
>>> x = [1,2,3,4,5]
>>> x<2
False
>>> x[False]
1
>>> x[True]
2
Bool basitçe bir tam sayıya dönüştürülür. Dizin 0 veya 1'dir.
x
ve 2
vardır " tutarlı ama keyfi sipariş " ve sipariş farklı Python uygulamalarda değişebileceğini.
x<2 == false
?
bool
tam sayıya dönüştürülmez, bool
Python'da a bir tam sayıdır
bool
bir alt sınıfıdır arasında int
.
Sorunuza orijinal kod ise sadece Python 2. çalışır x
bir olan list
Python 2'de, karşılaştırma x < y
olup False
olmadığını y
bir olduğunu int
eger. Bunun nedeni, bir listeyi bir tamsayı ile karşılaştırmanın mantıklı olmamasıdır. Ancak Python 2'de, işlenenler karşılaştırılabilir değilse, karşılaştırma CPython'da türlerin adlarının alfabetik sıralanmasına dayanır ; ayrıca karışık tip karşılaştırmalarda tüm sayılar önce gelir . Bu, CPython 2'nin belgelerinde bile belirtilmemiştir ve farklı Python 2 uygulamaları farklı sonuçlar verebilir. Yani [1, 2, 3, 4, 5] < 2
olarak değerlendirilirse False
, çünkü 2
bir dizi ve bir daha nedenle "küçük" olduğunu list
CPython içinde. Bu karışık karşılaştırma sonundabir özelliği çok belirsiz olarak kabul edildi ve Python 3.0'da kaldırıldı.
Şimdi, sonucu <
a bool
; ve bool
bir olan alt sınıf arasındaint
:
>>> isinstance(False, int)
True
>>> isinstance(True, int)
True
>>> False == 0
True
>>> True == 1
True
>>> False + 5
5
>>> True + 5
6
Yani temelde karşılaştırmanın doğru veya yanlış olmasına bağlı olarak 0 veya 1 öğesini alıyorsunuz.
Yukarıdaki kodu Python 3'te denerseniz, Python 3.0'daki bir değişiklikTypeError: unorderable types: list() < int()
nedeniyle alacaksınız :
Sıralama Karşılaştırmaları
Python 3.0, karşılaştırmaları sıralama kurallarını basitleştirdi:
Sipariş karşılaştırma operatörleri (
<
,<=
,>=
,>
) bir zamTypeError
işlenenler anlamlı doğal sipariş olmadığı zamanlarda istisna. Böylece, ifadeler gibi1 < ''
,0 > None
ya dalen <= len
artık geçerli ve örneğinNone < None
artırmalarTypeError
döndürmek yerineFalse
. Sonuç olarak, heterojen bir listeyi sıralamak artık mantıklı değildir - tüm öğeler birbiriyle karşılaştırılabilir olmalıdır. Bunun==
ve!=
operatörleri için geçerli olmadığını unutmayın : farklı karşılaştırılamaz türdeki nesneler her zaman birbirleriyle eşit olmayanları karşılaştırır.
Karşılaştırma işleçlerini farklı bir şey yapmak için aşırı yükleyen birçok veri türü vardır (pandalardan gelen veri çerçeveleri, numpy dizileri). Kullandığınız kod başka bir şey yaptıysa, bunun nedeni a değil , başka bir sınıfın örneğidir, operatörün a olmayan bir değer döndürmek için geçersiz kılınması ; ve bu değer daha sonra (aka / ) tarafından özel olarak işlendix
list
<
bool
x[]
__getitem__
__setitem__
+False
Merhaba Perl, hey JavaScript, nasılsınız?
UNARY_POSITIVE
__pos__
__setitem__
yerine demek istedin __getitem__
. Ayrıca cevabımın cevabınızın bu kısmından ilham aldığını umarım.
__getitem__
de aynı şekilde __setitem__
ve__delitem__
Bunun bir kullanımı daha var: kod golf. Kod golfü, bazı sorunları olabildiğince az kaynak kodu baytında çözen programlar yazma sanatıdır.
return(a,b)[c<d]
kabaca eşdeğerdir
if c < d:
return b
else:
return a
hem a hem de b'nin birinci sürümde değerlendirilmesinin dışında, ikinci sürümde değerlendirilmemesi dışında.
c<d
True
veya olarak değerlendirir False
.
(a, b)
bir gruptur.
Bir demet üzerinde indeksleme, bir listede indeksleme gibi çalışır: (3,5)[1]
== 5
.
True
eşittir 1
ve False
eşittir 0
.
(a,b)[c<d]
(a,b)[True]
(a,b)[1]
b
veya için False
:
(a,b)[c<d]
(a,b)[False]
(a,b)[0]
a
Yığın değişim ağında, birkaç bayt tasarruf etmek için python'a yapabileceğiniz birçok kötü şeyin iyi bir listesi var. /codegolf/54/tips-for-golfing-in-python
Normal kodda bu asla kullanılmamalıdır ve sizin durumunuzda bu, x
hem bir tamsayı ile karşılaştırılabilecek bir şey olarak hem de çok sıra dışı bir kombinasyon olan dilimlemeyi destekleyen bir kap olarak hareket ettiği anlamına gelir . Başkalarının da belirttiği gibi, muhtemelen geçersiz koddur.
Code Golf is the art of writing programs
: ')
Genel olarak herhangi bir şey ifade edebilir . Zaten olsaydı ne anlama geldiğini açıkladı x
bir olduğunu list
ya numpy.ndarray
ama genel olarak sadece karşılaştırma operatörleri (bağlıdır <
, >
, ...) ve ayrıca get / set maddelik (nasıl [...]
-syntax) uygulanmaktadır.
x.__getitem__(x.__lt__(2)) # this is what x[x < 2] means!
x.__setitem__(x.__lt__(2), 0) # this is what x[x < 2] = 0 means!
Çünkü:
x < value
eşdeğerdir x.__lt__(value)
x[value]
(kabaca) eşdeğerdir x.__getitem__(value)
x[value] = othervalue
(aynı zamanda kabaca) eşdeğerdir x.__setitem__(value, othervalue)
.Bu, istediğiniz herhangi bir şeyi yapmak için özelleştirilebilir . Örnek olarak (biraz numpys-boolean indekslemeyi taklit eder):
class Test:
def __init__(self, value):
self.value = value
def __lt__(self, other):
# You could do anything in here. For example create a new list indicating if that
# element is less than the other value
res = [item < other for item in self.value]
return self.__class__(res)
def __repr__(self):
return '{0} ({1})'.format(self.__class__.__name__, self.value)
def __getitem__(self, item):
# If you index with an instance of this class use "boolean-indexing"
if isinstance(item, Test):
res = self.__class__([i for i, index in zip(self.value, item) if index])
return res
# Something else was given just try to use it on the value
return self.value[item]
def __setitem__(self, item, value):
if isinstance(item, Test):
self.value = [i if not index else value for i, index in zip(self.value, item)]
else:
self.value[item] = value
Şimdi onu kullanırsanız ne olacağını görelim:
>>> a = Test([1,2,3])
>>> a
Test ([1, 2, 3])
>>> a < 2 # calls __lt__
Test ([True, False, False])
>>> a[Test([True, False, False])] # calls __getitem__
Test ([1])
>>> a[a < 2] # or short form
Test ([1])
>>> a[a < 2] = 0 # calls __setitem__
>>> a
Test ([0, 2, 3])
Bunun sadece bir olasılık olduğuna dikkat edin. Neredeyse istediğiniz her şeyi uygulamakta özgürsünüz.