Здесь есть замечательные ответы на эти вопросы, которые вовлекают во всевозможные подробные сведения о интерфейсах и слабосвязанный код, инверсию управления и т. д. Есть несколько довольно острых дискуссий, поэтому я хотел бы воспользоваться возможностью немного разобраться в том, почему интерфейс полезен.
Когда я впервые начал работать с интерфейсами, я тоже был смущен об их значимости. Я не понимал, зачем вам это нужно. Если мы используем такой язык, как Java или C #, у нас уже есть наследование, и я рассматривал интерфейсы как более слабую форму наследования и мысли «зачем беспокоиться»? В некотором смысле я был прав, вы можете думать о интерфейсах как о какой-то слабой форме наследования, но помимо этого я, наконец, понял их использование в качестве языковой конструкции, считая их как средство классификации общих черт или моделей поведения, которые были представлены потенциально много несвязанных классов объектов.
Например, скажем, у вас есть игра с SIM-картой, и у вас есть следующие классы:
class HouseFly inherits Insect {
void FlyAroundYourHead(){}
void LandOnThings(){}
}
class Telemarketer inherits Person {
void CallDuringDinner(){}
void ContinueTalkingWhenYouSayNo(){}
}
Очевидно, что эти два объекта не имеют ничего в общий с точки зрения прямого наследования. Но вы могли бы сказать, что они оба раздражают.
Предположим, что в нашей игре должно быть какое-то случайное вещь , которая раздражает игрока, когда они едят обед. Это могут быть HouseFly
или Telemarketer
или оба, но как вы можете использовать обе функции с одной функцией? И как вы просите каждый из разных типов объектов «делать свою раздражающую вещь» таким же образом?
Ключом к пониманию является то, что как Telemarketer
, так и HouseFly
имеют общее слабо интерпретируемое поведение даже несмотря на то, что они не имеют ничего общего с их моделированием. Итак, давайте создадим интерфейс, который оба могут реализовать:
interface IPest {
void BeAnnoying();
}
class HouseFly inherits Insect implements IPest {
void FlyAroundYourHead(){}
void LandOnThings(){}
void BeAnnoying() {
FlyAroundYourHead();
LandOnThings();
}
}
class Telemarketer inherits Person implements IPest {
void CallDuringDinner(){}
void ContinueTalkingWhenYouSayNo(){}
void BeAnnoying() {
CallDuringDinner();
ContinueTalkingWhenYouSayNo();
}
}
Теперь у нас есть два класса, каждый из которых может раздражать по-своему. И им не нужно выводить из одного базового класса и обладать общими присущими характеристиками - им просто нужно удовлетворить контракт IPest
- этот контракт прост. Вам просто нужно BeAnnoying
. В этой связи мы можем моделировать следующее:
class DiningRoom {
DiningRoom(Person[] diningPeople, IPest[] pests) { ... }
void ServeDinner() {
when diningPeople are eating,
foreach pest in pests
pest.BeAnnoying();
}
}
Здесь у нас есть столовая, в которой принимают несколько посетителей и несколько вредителей - обратите внимание на использование интерфейса. Это означает, что в нашем маленьком мире членом массива pests
может быть объект Telemarketer
или объект HouseFly
.
Метод ServeDinner
вызывается при подаче обеда и наши люди в столовой должны есть. В нашей маленькой игре, вот когда наши вредители выполняют свою работу - каждый вредитель инструктируется быть раздражающим через интерфейс IPest
. Таким образом, мы с легкостью можем раздражать как Telemarketers
, так и HouseFlys
в каждом из своих способов - мы заботимся только о том, что у нас есть что-то в объекте DiningRoom
, являющемся вредителем, нам все равно что это такое, и они не могли иметь ничего общего с другими.
Этот очень надуманный пример псевдокода (который тянулся намного дольше, чем я ожидал) просто предназначен для иллюстрации того, что, наконец, включило свет для меня с точки зрения того, когда мы могли бы использовать интерфейс. Я заранее извиняюсь за глупость примера, но надеюсь, что это поможет в вашем понимании. И, конечно же, другие опубликованные ответы, которые вы получили здесь, действительно охватывают диапазон использования интерфейсов сегодня в шаблонах проектирования и методологиях разработки.
Ваша функция может быть выполнена для работы путем повторения по списку в обратном порядке:
def checkio(data):
for index in range(len(data) - 1, -1, -1):
if data.count(data[index]) == 1:
del data[index]
return data
print(checkio([3, 3, 5, 8, 1, 4, 5, 2, 4, 4, 3, 0]))
[3, 3, 5, 4, 5, 4, 4, 3]
print(checkio([1, 2, 3, 4]))
[]
Это работает, поскольку оно только удаляет числа в разделе списка, который уже был повторен.
Вы можете реализовать OrderedCounter
, например:
from collections import OrderedDict, Counter
class OrderedCounter(Counter, OrderedDict):
pass
data = [1, 3, 1, 2, 3, 5, 8, 1, 5, 2]
duplicates = [k for k, v in OrderedCounter(data).items() if v > 1]
# [1, 3, 2, 5]
. Таким образом, вы подсчитываете появление каждого значения, а затем фильтруете, если он имеет частоту более одного. Наследование с OrderedDict
означает, что порядок исходных элементов сохраняется.
. По комментариям вы хотите, чтобы все дублированные элементы были зарезервированы, поэтому вы можете предварительно создать набор повторяющихся записей, затем повторите итерацию исходного списка, например:
from collections import Counter
data = [1, 3, 1, 2, 3, 5, 8, 1, 5, 2]
duplicates = {k for k, v in Counter(data).items() if v > 1}
result = [el for el in data if el in duplicates]
# [1, 3, 1, 2, 3, 5, 1, 5, 2]
После того, что вы начали, повторяя в списке целых чисел, но не считая или удаляя элементы, попробуйте просто проверить, был ли элемент уже просмотрен, добавьте его в список дублированных элементов:
def checkio(data):
elements = []
duplicates = []
for i in data:
if i not in elements:
elements.append(i)
else:
if i not in duplicates:
duplicates.append(i)
return duplicates
d = [1, 3, 1, 2, 3, 5, 8, 1, 5, 2]
print (checkio(d))
#[1, 3, 5, 2]
Попробуйте следующее:
>>> a=[1,2,3,3,4,5,6,6,7,8,9,2,0,0]
>>> a=[i for i in a if a.count(i)>1]
>>> a
[2, 3, 3, 6, 6, 2, 0, 0]
>>> a=[1, 2, 3, 1, 3]
>>> a=[i for i in a if a.count(i)>1]
>>> a
[1, 3, 1, 3]
>>> a=[1, 2, 3, 4, 5]
>>> a=[i for i in a if a.count(i)>1]
a
[]
def checkio(data):
lis = []
for i in data:
if data.count(i)>1:
lis.append(i)
print(lis)
checkio([1,2,3,3,2,1])
Да, немного поздно внести свой вклад в эту тему, но просто хотел поместить ее туда в сети, чтобы кто-то еще использовал ее.
Просто я использовал список «Понимание».
def checkio(data):
a=[i for i in data if data.count(i)>1]
return a
print checkio([1,1,2,2,1,1,1,3,4,5,6,7,8])
O(n)
) решение - использоватьCounter
. – Aran-Fey 31 March 2018 в 15:47