2015-08-06 2 views
0

Я соскабливаю веб-сайт, содержащий список людей. Тот же человек может показать больше, чем один раз, и это возможно для нескольких людей, чтобы одни и те же имя:Как я могу убедиться, что значение атрибута уникально в Python?

Tommy Atkins (id:312) 
Tommy Atkins (id:183) 
Tommy Atkins (id:312) 

Я хочу создать объект для каждого человека и отбросить дубликаты.

В настоящее время я использую представление списка для проверки всех экземпляров класса и выяснения, используется ли key. Есть ли более простой способ сделать это?

class Object: 
    def __init__(self, key): 
     if [object for object in objects if object.key == key]: 
      raise Exception('key {} already exists'.format(key)) 
     else: self.key = key 

objects = [] 
objects.append(Object(1)) 
objects.append(Object(1)) # Exception: key 1 already exists 

ответ

1

Определение __eq__ и __hash__ в вашем классе, сравните экземпляры на основе значения key и вычислите хэш, используя его. И вместо списка использовать set, как он будет автоматически фильтровать дубликаты для вас эффективным способом:

class Object: 
    def __init__(self, key): 
     self.key = key 

    def __eq__(self, other): 
     if isinstance(other, type(self)): 
      return self.key == other.key 
     return NotImplemented 

    def __ne__(self, other): 
     return not type(self).__eq__(self, other) 

    def __hash__(self): 
     return hash(self.key) 


objects = set() 
o1 = Object(1) 
o2 = Object(1) 
objects.add(o1) 
objects.add(o2) 

print (o1, o2) # <__main__.Object object at 0x105996ba8> <__main__.Object object at 0x105996be0> 
print (objects) # {<__main__.Object object at 0x105996ba8>} 

Не назначайте экземпляров постоянно переменной, в противном случае он не будет мусора (Обратите внимание, что это верно только для CPython):

objects = set() 

for _ in range(5): 
    ins = Object(1) 
    print(id(ins)) 
    objects.add(ins) 

Выход:

4495640448 # First instance and this is now stored in the set 
      # hence it is not going to be garbage collected. 
4495640840 # Python is now using new memory space. 
4495640896 # Right now 4495640840 is still owned by the 
      # previous instance, hence use new memory address 
      # But after this assignment the instance at 4495640840 
      # has no more references, i.e ins now points to 4495640896 
4495640840 # Re-use 4495640840 
4495640896 # Repeat... 
+0

нет ли способ предотвратить создание экземпляров, если к ey уже используется? Я не знаком с управлением памятью в Python, но создание всех этих объектов кажется расточительным. – fenceop

+1

@fenceop Не назначайте экземпляр какой-либо переменной, любой объект без ссылки слева будет автоматически собирать мусор. –

0

Глобальное хранилище для ид хорошо, но его лучше использовать set вместо list для этого, как проверка i in {} является O (1), а i in [] является O (N)

Смежные вопросы