gpt4 book ai didi

python:字典困境:如何根据属性正确索引对象

转载 作者:太空宇宙 更新时间:2023-11-03 11:11:20 27 4
gpt4 key购买 nike

先举个例子:

given a bunch of Person objects with various attributes (name, ssn, phone, email address, credit card #, etc.)

now imagine the following simple website:

  1. uses a person's email address as unique login name
  2. lets users edit their attributes (including their email address)

if this website had tons of users, then it make sense to store Person objects in a dictionary indexed by email address, for quick Person retrieval upon login.

however when a Person's email address is edited, then the dictionary key for that Person needs to be changed as well. this is slightly yucky

我正在寻找有关如何解决一般问题的建议:

给定一堆具有共同方面的实体。该方面既用于快速访问实体,也用于每个实体的功能。 aspect应该放在哪里:

  1. 在每个实体内(不利于快速访问)
  2. 仅索引(不利于每个实体的功能)
  3. 在每个实体内和作为索引(重复数据/引用)
  4. 在其他地方/以某种方式不同

问题可能会扩展,比如说,如果我们想使用多个索引来索引数据(ssn、信用卡号等)。最终我们可能会得到一堆 SQL 表。

我正在寻找具有以下属性的东西(如果你能想到的话,还有更多):

# create an index on the attribute of a class
magical_index = magical_index_factory(class, class.attribute)
# create an object
obj = class()
# set the object's attribute
obj.attribute= value
# retrieve object from using attribute as index
magical_index[value]
# change object attribute to new value
obj.attribute= new_value
# automagically object can be retrieved using new value of attribute
magical_index[new_value]
# become less materialistic: get rid of the objects in your life
del obj
# object is really gone
magical_index[new_value]
KeyError: new_value

我希望对象、索引都能很好地无缝地相互配合。

请建议合适的设计模式

注意:上面的例子只是一个例子。一个用来描述一般问题的例子。所以请提供通用的解决方案(当然,您在解释您的通用解决方案时可以选择继续使用该示例)

最佳答案

考虑一下。

class Person( object ):
def __init__( self, name, addr, email, etc. ):
self.observer= []
... etc. ...
@property
def name( self ): return self._name
@name.setter
def name( self, value ):
self._name= value
for observer in self.observedBy: observer.update( self )
... etc. ...

这个observer 属性实现了一个Observable,通知它的Observers 更新。这是必须通知更改的观察者列表。

每个属性都用属性包装。使用 Descriptors 我们可能会更好,因为它可以避免重复观察者通知。

class PersonCollection( set ):
def __init__( self, *args, **kw ):
self.byName= collections.defaultdict(list)
self.byEmail= collections.defaultdict(list)
super( PersonCollection, self ).__init__( *args, **kw )
def add( self, person ):
super( PersonCollection, self ).append( person )
person.observer.append( self )
self.byName[person.name].append( person )
self.byEmail[person.email].append( person )
def update( self, person ):
"""This person changed. Find them in old indexes and fix them."""
changed = [(k,v) for k,v in self.byName.items() if id(person) == id(v) ]
for k, v in changed:
self.byName.pop( k )
self.byName[person.name].append( person )
changed = [(k,v) for k,v in self.byEmail.items() if id(person) == id(v) ]
for k, v in changed:
self.byEmail.pop( k )
self.byEmail[person.email].append( person)

... etc. ... for all methods of a collections.Set.

使用 collections.ABC 获取有关必须实现的内容的更多信息。

http://docs.python.org/library/collections.html#abcs-abstract-base-classes

如果你想要“通用”索引,那么你的集合可以用属性名称参数化,你可以使用 getattr 从底层对象中获取那些命名属性。

class GenericIndexedCollection( set ):
attributes_to_index = [ ] # List of attribute names
def __init__( self, *args, **kw ):
self.indexes = dict( (n, {}) for n in self.attributes_to_index ]
super( PersonCollection, self ).__init__( *args, **kw )
def add( self, person ):
super( PersonCollection, self ).append( person )
for i in self.indexes:
self.indexes[i].append( getattr( person, i )

注意。要正确模拟数据库,请使用集合而不是列表。数据库表(理论上)是集合。实际上,它们是无序的,索引将允许数据库拒绝重复项。某些 RDBMS 不会拒绝重复行,因为没有索引,检查起来成本太高。

关于python:字典困境:如何根据属性正确索引对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2305798/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com