Python'daki tilde operatörü


201

Tilde operatörünün Python'da kullanımı nedir?

Düşünebileceğim bir şey, bir dizenin palindromik olup olmadığını kontrol etmek gibi bir dizenin veya listenin her iki tarafında bir şey yapmaktır:

def is_palindromic(s):
    return all(s[i] == s[~i] for i in range(len(s) / 2)) 

Başka iyi kullanım var mı?


11
~Özel yöntemle uygulanan tekli tamamlayıcı operatörünün işleçle __invert__ilgisi olmadığını not, bu da döndürülen değeri mantıksal olarak __bool__(veya __nonzero__2.x'te) reddettiğini unutmayın. Ayrıca -, tarafından uygulanan tekli olumsuzlama operatörü ile de ilgisizdir __neg__. Örneğin ~True == -2, hangisi Falseyanlıştır -False == 0, hangisi yanlıştır.
Eryk Sun

@eryksun, söyledikleriniz doğru olsa da ( -False==0) Bu kafa karıştırıcı, çünkü hakkında konuşuyordunuz ~ve ~False == -1bu Yanlış değil.
Guilherme de Lazari

3
@GuilhermedeLazari, ikinci örnek aritmetik olumsuzlama ( __neg__) ile karşılaştırmaktı . Muhtemelen kullanmaya devam etmeliydim True, örneğin -True == -1, -2 veya Falseyanlış olmayan, ~Truesonuca daha açık bir şekilde geri bağlayan ve ayrıca a'nın aritmetik olumsuzlaması boolmantıksal olumsuzluğundan farklıdır. Derin olmaya çalışmıyordum. Sadece 3 operasyon ve bazen karışan altta yatan özel yöntemleri vurguladım.
Eryk Sun

Yanıtlar:


194

Tüm veri türlerinin baytları yorumlamanın yalnızca farklı yolları olduğu C'den ödünç alınan tek bir argüman (tek bir argüman alarak). Giriş verilerinin tüm bitlerinin ters çevrildiği "ters çevir" veya "tamamlayıcı" işlemidir.

Python'da, tamsayılar için, tamsayının iki tamamlayıcı gösteriminin bitleri tersine çevrilir ( b <- b XOR 1her bir ayrı bit için olduğu gibi ) ve sonuç yine bir iki tamamlayıcı tam sayı olarak yorumlanır. Yani tamsayılar için ~x, eşdeğerdir (-x) - 1.

Hayli durağan bir şekilde ~operatör olarak sağlanır operator.invert. Bu operatörü kendi sınıfınızda desteklemek için ona bir __invert__(self)yöntem verin .

>>> import operator
>>> class Foo:
...   def __invert__(self):
...     print 'invert'
...
>>> x = Foo()
>>> operator.invert(x)
invert
>>> ~x
invert

Aynı sınıfın bir örneği olan bir örneğin "tamamlayıcısı" veya "tersine" sahip olmasının anlamlı olduğu herhangi bir sınıf, ters çevirme operatörü için olası bir adaydır. Bununla birlikte, operatörün aşırı yüklenmesi, yanlış kullanıldığında karışıklığa neden olabilir, bu nedenle __invert__sınıfınıza bir yöntem sağlamadan önce gerçekten mantıklı olduğundan emin olun . (Bayt dizelerinin [ex: '\xff'] bir bayt dizesinin tüm bitlerini ters çevirmek anlamlı olsa da bu operatörü desteklemediğini unutmayın.)


17
İyi bir açıklama, ancak bir uyarı kelimesi - operatörün aşırı yüklenmesi için tüm güvenlik feragatnameleri burada geçerlidir - faturaya tam olarak uymadıkça iyi bir fikir değildir.
Eli Bendersky

Eli'nin geri bildirimi, son paragraftaki cevaba dahil edildi.
wberry

91

~bir bit-bazında bütünleyici operatör esas hesaplar python-x - 1

Yani bir masa

i  ~i  
0  -1
1  -2
2  -3
3  -4 
4  -5 
5  -6

Yani için i = 0o karşılaştırmak istiyorsunuz s[0]ile s[len(s) - 1]için, i = 1, s[1]ile s[len(s) - 2].

Diğer sorunuza gelince, bu bir dizi bitsel hack için yararlı olabilir .


26

Bitsel bir tamamlayıcı operatör olmasının yanı sıra, burada geleneksel tip olmasa da, kullanmanız gereken ~bir boolean değerinin geri alınmasına yardımcı olabilir .boolnumpy.bool_


Bu,

import numpy as np
assert ~np.True_ == np.False_

Ters mantıksal değer bazen yararlı olabilir, örneğin, ~veri kümenizi temizlemek ve NaN'siz bir sütun döndürmek için aşağıdaki operatör kullanılır.

from numpy import NaN
import pandas as pd

matrix = pd.DataFrame([1,2,3,4,NaN], columns=['Number'], dtype='float64')
# Remove NaN in column 'Number'
matrix['Number'][~matrix['Number'].isnull()]

numpy.NaNolarak tanımlanmış görünüyor numpy.float. Eğer ~numpy.NaNdenersem, python, tekli operatörün ~tür için tanımlanmadığından şikayet eder numpy.float.
M.Herzkamp

2
@ M.Herzkamp, ​​bu doğru. NaN, + Inf ve -Inf kayan nokta sayılarının özel durumlarıdır. Kayan nokta sayısının bitlerini tersine çevirmek saçma bir sonuç doğurur, bu nedenle Python buna izin vermez. Bu nedenle önce veri dizinizde .isnull () veya np.isnan () öğesini çağırmanız ve ardından elde edilen boole değerlerini ters çevirmeniz gerekir.
geofflee

7
Bu ~Truesonuçla sonuçlanırken -2, numpy booleans için ~np.True_sonuç verir False.
Christian Herenz

iyi bahşiş! Burada bir veri kümesini sıralamak için kullanıldığını gördüm: github.com/yu4u/age-gender-estimation/blob/master/create_db.py
mLstudent33

19

Dizi indeksleme durumunda, array[~i]değerin belirtilmesi gerekir reversed_array[i]. Dizinin sonundan başlayarak dizin oluşturma olarak görülebilir:

[0, 1, 2, 3, 4, 5, 6, 7, 8]
    ^                 ^
    i                ~i

2
Çoğunlukla çıkan değer ~i(yani negatif değer), python'un dizinin etrafına sarılmasına ve arkadan toplanmasına neden olan mutlu bir şekilde kabul ettiği dizi dizini için bir başlangıç ​​noktası görevi görmesidir.
shriek

4

Bunu pratikte kullandığım tek zaman numpy/pandas. Örneğin, .isin() veri çerçevesi yöntemiyle .

Dokümanlarda bu temel örneği gösterirler

>>> df.isin([0, 2])
        num_legs  num_wings
falcon      True       True
dog        False       True

Peki ya [0, 2] 'de olmayan tüm satırları isteseydiniz ?

>>> ~df.isin([0, 2])
        num_legs  num_wings
falcon     False       False
dog        True        False

2

Bu leetcode problemini çözüyordum ve Zitao Wang adlı bir kullanıcı tarafından bu güzel çözüme rastladım .

Sorun, verilen dizideki her öğe için, bölme ve O(n)zaman kullanmadan kalan tüm sayıların ürününü bulmak için bu şekilde gider

Standart çözüm:

Pass 1: For all elements compute product of all the elements to the left of it
Pass 2: For all elements compute product of all the elements to the right of it
        and then multiplying them for the final answer 

Onun çözümü kullanarak sadece bir döngü kullanır. Sol ürünü ve sağ ürünü anında kullanarak hesaplar.~

def productExceptSelf(self, nums):
    res = [1]*len(nums)
    lprod = 1
    rprod = 1
    for i in range(len(nums)):
        res[i] *= lprod
        lprod *= nums[i]
        res[~i] *= rprod
        rprod *= nums[~i]
    return res

-2

Bu küçük kullanım tilde olduğunu ...

def split_train_test_by_id(data, test_ratio, id_column):
    ids = data[id_column]
    in_test_set = ids.apply(lambda id_: test_set_check(id_, test_ratio)) 
    return data.loc[~in_test_set], data.loc[in_test_set]

Yukarıdaki kod "Hands On Machine Learning" den alınmıştır.

- işaret indeksi işaretleyicisine alternatif olarak tilde (~ sign) kullanırsınız

tıpkı eksi kullandığınız gibi - tamsayı dizini içindir

ex)

array = [1,2,3,4,5,6]
print(array[-1])

gibi bir şey mi

print(array[~1])

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.