Оператор тильды в Python

#python

#python #операторы

Вопрос:

Как используется оператор тильды в Python?

Одна вещь, о которой я могу подумать, это сделать что-то с обеих сторон строки или списка, например, проверить, является ли строка палиндромной или нет:

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

Любое другое хорошее использование?

Комментарии:

1. Обратите внимание, что оператор унарного дополнения ~ , реализованный специальным методом __invert__ , не связан с not оператором, который логически отрицает значение, возвращаемое __bool__ (или __nonzero__ в 2.x). Он также не связан с оператором - унарного отрицания, реализованным __neg__ . Например ~True == -2 , который не False является или false , и -False == 0 , который по-прежнему false .

2. @eryksun, хотя то, что ты сказал, правильно ( -False==0 ) Это сбивает с толку, поскольку вы говорили о ~ , и ~False == -1 который не является ложным.

3. @GuilhermedeLazari, вторым примером было сравнение с арифметическим отрицанием ( __neg__ ). Вероятно, мне следовало продолжить использовать True , например -True == -1 , который не равен -2 или False или false , что более четко связывает его с ~True результатом, а также с тем, что арифметическое отрицание a bool отличается от его логического отрицания. Я не пытался быть глубоким. Я просто выделил 3 операции и лежащие в их основе специальные методы, которые иногда путаются.

4. Смотрите также: tutorialspoint.com/python/python_basic_operators.htm —> Раздел «Побитовые операторы Python».

Ответ №1:

Это унарный оператор (принимающий один аргумент), который заимствован из C, где все типы данных — это просто разные способы интерпретации байтов. Это операция «инвертирования» или «дополнения», при которой все биты входных данных меняются местами.

В Python для целых чисел биты представления целого числа с двумя дополнениями меняются местами (как b <- b XOR 1 для каждого отдельного бита), и результат снова интерпретируется как целое число с двумя дополнениями. Таким образом, для целых ~x чисел эквивалентно (-x) - 1 .

Конкретизированная форма ~ оператора предоставляется как operator.invert . Чтобы поддерживать этот оператор в вашем собственном классе, дайте ему __invert__(self) метод.

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

Любой класс, в котором имеет смысл иметь «дополнение» или «инверсию» экземпляра, который также является экземпляром того же класса, является возможным кандидатом на оператор инвертирования. Однако перегрузка оператора может привести к путанице при неправильном использовании, поэтому убедитесь, что это действительно имеет смысл сделать, прежде чем предоставлять __invert__ метод вашему классу. (Обратите внимание, что байтовые строки [например: 'xff' ] не поддерживают этот оператор, хотя имеет смысл инвертировать все биты байтовой строки.)

Ответ №2:

~ является ли оператор побитового дополнения в python, который по существу вычисляет -x - 1

Таким образом, таблица будет выглядеть так

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

Так что для i = 0 него будет сравниваться s[0] с s[len(s) - 1] , для i = 1 , s[1] с s[len(s) - 2] .

Что касается вашего другого вопроса, это может быть полезно для ряда побитовых взломов.

Ответ №3:

Помимо того, что он является оператором побитового дополнения, ~ он также может помочь вернуть логическое значение, хотя здесь это не обычный bool тип, скорее вы должны использовать numpy.bool_ .


Это объясняется в,

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

Иногда может быть полезно изменить логическое значение, например, ~ оператор below используется для очистки вашего набора данных и возврата столбца без NaN.

 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()]
 

Комментарии:

1. numpy.NaN кажется, определяется как numpy.float . Если я попытаюсь ~numpy.NaN , python пожалуется, что унарный оператор ~ не определен для типа numpy.float .

2. @M.Herzkamp, это правильно. NaN, Inf и -Inf являются частными случаями чисел с плавающей запятой. Инвертирование битов числа с плавающей запятой приведет к бессмысленному результату, поэтому Python этого не допускает. Вот почему вам нужно сначала вызвать .isnull() или np.isnan() в вашем массиве данных, а затем инвертировать полученные логические значения.

3. Обратите внимание, что ~True это приводит к -2 , в то время как для логических значений numpy ~np.True_ приводит к False .

4. хороший совет! Я видел, как он использовался здесь для сортировки набора данных: github.com/yu4u/age-gender-estimation/blob/master/create_db.py

Ответ №4:

Следует отметить, что в случае индексации массива, array[~i] составляет reversed_array[i] . Это можно рассматривать как индексацию, начиная с конца массива:

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

Комментарии:

1. Это в основном потому, что значение, которое получается из ~i (т. Е. Отрицательное значение), действует как отправная точка для индекса массива, который python с радостью принимает, заставляя индекс обтекать и выбирать сзади.

Ответ №5:

Единственный раз, когда я когда-либо использовал это на практике, — with numpy/pandas . Например, с помощью .isin() метода dataframe.

В документах они показывают этот базовый пример

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

Но что, если вместо этого вы хотите, чтобы все строки не были в [0, 2] ?

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

Ответ №6:

Я решал эту проблему с leetcode и наткнулся на это прекрасное решение пользователя по имени Zitao Wang.

Задача выглядит следующим образом для каждого элемента в данном массиве найдите произведение всех оставшихся чисел без использования divison и во O(n) времени

Стандартным решением является:

 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 
 

Его решение использует только один цикл for, используя. Он вычисляет левое произведение и правое произведение на лету, используя ~

 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
 

Ответ №7:

это называется двоичным дополнением (~)

Он возвращает дополнение единицы к двоичному коду числа. Он переворачивает биты. Двоичный файл для 2 равен 00000010. Его единственным дополнением является 11111101.

Это двоичный файл для -3. Итак, это приводит к -3. Аналогично, ~1 приводит к -2.

 ~-3
 

Вывод : 2

Опять же, одно дополнение к -3 равно 2.

Комментарии:

1. Этот ответ смешивает комплименты одного и двух. Например, в 4-битах 1101 -3 в комплименте two , но равно -2 в комплименте one. Кроме того, примеры преобразования повсюду и не поддерживают логический поток повсюду.

Ответ №8:

Это незначительное использование тильды…

 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]
 

приведенный выше код взят из «Практического машинного обучения»

вы используете тильду (~ sign) в качестве альтернативы индексному маркеру — sign

точно так же, как вы используете минус — это для целочисленного индекса

пример)

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

является ли то же самое, что и

print(array[~1])