Una versione di Python shelve module che sa quando le sue voci sono state modificate può essere scritta in qualsiasi linguaggio di programmazione?

1

shelve è un modulo Python che semplifica la permanenza di un dizionario Python su disco (nelle giuste condizioni).

La documentazione per shelve fornisce questo esempio per dimostrare una delle trappole dell'uso di uno scaffale:

import shelve

d = shelve.open(filename)

# ...snip...

# as d was opened WITHOUT writeback=True, beware:
d['xx'] = range(4)  # this works as expected, but...
d['xx'].append(5)   # *this doesn't!* -- d['xx'] is STILL range(4)!

La documentazione spiega:

Because of Python semantics, a shelf cannot know when a mutable persistent-dictionary entry is modified. By default modified objects are written only when assigned to the shelf (see Example).

Dire che gli scaffali si comportano in questo modo "a causa della semantica di Python" mi sembra che stia misurando Python tramite una barra alta! Sarebbe difficile per accantonare sapere se qualsiasi oggetto contenuto in una mensola ha un riferimento a qualcosa che è stato mutato (o un riferimento a qualcosa che ha un riferimento a qualcosa che è stato mutato). Questo può essere fatto in qualsiasi linguaggio di programmazione?

    
posta kuzzooroo 06.07.2014 - 19:33
fonte

2 risposte

3

No, questo non è solo un problema di Python.

Risolvere la domanda "è stato modificato questo oggetto da quando X è successo?" (in questo caso, l'oggetto che viene aggiunto al dizionario) richiederebbe una delle due cose. O usi oggetti immutabili, nel qual caso la risposta è sempre "no" e la domanda è piuttosto priva di significato, o hai qualche modo di notare quando un oggetto viene modificato in qualsiasi modo.

Per quanto ne so, nessuna lingua lo fa automaticamente. Il framework .NET ha un concetto di "proprietà osservabili" che genera un evento quando la proprietà viene modificata, ma devono essere implementate manualmente e funzioneranno solo per le proprietà sull'oggetto stesso. (Se l'oggetto ha un sub-oggetto che viene modificato, cambierebbe anche la rappresentazione serializzata dell'oggetto principale.) Quindi no; questo potrebbe essere un problema "a causa della semantica Python" ma è dovuto alla semantica orientata agli oggetti in generale.

    
risposta data 07.07.2014 - 00:36
fonte
2

È perfettamente fattibile, anche in Python. Il trucco sta nel restituire un wrapper al posto dell'oggetto originale memorizzato.

nel tuo esempio:

d['xx'] = range(4)
d['xx'].append(5)

la seconda riga può essere estesa in un recupero e un'operazione:

d['xx'] = range(4)
t = d['xx']
t.append(5)

ed è ovvio che t non notifica d sull'operazione .append() .

ma se restituisci un object wrapper w che mantiene un riferimento a d e la chiave 'xx' , potrebbe seguire qualsiasi operazione con la notifica appropriata.

qualcosa come (non testato!):

class wrapper():
  def __init__(self, container, key):
    self.container = container
    self.key = key
    self.value = container[key]

  def __getattr__(self, name):
    attr = getattr(self.value, name)
    if hasattr(attr, '__call__'):     # is callable?
      def f(*args, **kwargs):
        rv = attr(*args, **kwargs)   # do the call
        self.container[self.key] = self.value    # re-store the (modified?) value)
      return f
    return attr
    
risposta data 07.07.2014 - 15:45
fonte

Leggi altre domande sui tag