#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
результатом, а также с тем, что арифметическое отрицание abool
отличается от его логического отрицания. Я не пытался быть глубоким. Я просто выделил 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])