Seite 1 von 1
Konstruktur mit altem Selbst
Verfasst: Donnerstag 1. November 2007, 11:53
von gecko
Spricht etwas gegen die Überschreiben des Konstruktors mit einem alten selbst?
Code: Alles auswählen
class foo:
def __init__(self, data='initial data', oldfoo=None):
if oldfoo:
self.data = oldfoo.data
if data:
self.data = data
def __str__(self):
return 'my data: ' + self.data
if __name__=='__main__':
f = foo()
print f
g = foo('new data')
print g
h = foo('', g)
print h
Verfasst: Donnerstag 1. November 2007, 12:16
von Leonidas
Außer dem Fakt, dass wenn du sowohl `data` als auch `oldfoo` angibst, `oldfoo` keine Wirkung hat eigentlich nichts.
Ich mache es jedoch etwas anders:
Code: Alles auswählen
class Table(dict):
"""Simplified version of frozendict from
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/414283
This implementation is not hashable nor does it try to be.
It is meant to be used as a drop-in replacement for 'dict'
and throws AttributeErrors when trying to change it.
Do not expect absolute security from this code, it is only
meant to catch errors when one mistakenly alters keys in
this object instead of creating a new Table object based
on this one.
To create a new Table based on this one use
>>> Table(old_table, new_key='new_value')
>>> # or
>>> Table(old_table, { 'new_key' : 'new_value' })"""
def _blocked_attribute(obj):
"""This is called when trying to access a attribute which
modifies the state of this object"""
# blocked, complain
raise AttributeError("A Table cannot be modified")
# turn _blocked_attribute into a property
_blocked_attribute = property(_blocked_attribute)
# overwrite modifying methods with _blocked_attribute
__delitem__ = __setitem__ = clear = _blocked_attribute
pop = popitem = setdefault = update = _blocked_attribute
def __repr__(self):
"""Display the contents of the Table"""
return "Table(%s)" % dict.__repr__(self)
def update(table, updates, *args, **kwargs):
"""Updates a Table environment - it does not alter the Table,
instead it returns a new Table with the changes applied"""
# create a new empty dictionary to hold all values
new_table = dict()
# choin both dict-like objects together
all_items = itertools.chain(table.iteritems(), updates.iteritems())
# add all keys to the dictionary
for key, value in all_items:
new_table[key] = value
# convert the dictionary into a Table and return
return Table(new_table)
Damit habe ich eine Klasse, die immutable ist und die bei update() eine neue Klasseninstanz ausgibt, die eine aktualisierte Kopie seiner selbst zurückgibt.
Verfasst: Donnerstag 1. November 2007, 14:07
von BlackJack
@gecko: Die Frage ist, was Du durch das zusätziche Argument gewinnst. Du könntest bei dem Aufruf in Zeile 19 ja auch schreiben:
Falls `data` "intern" sein soll kann man auch `copy.copy()` oder eine eigene Methode zum Kopieren eines Objekts benutzen.
Verfasst: Donnerstag 1. November 2007, 15:33
von gecko
Ich habe jetzt gerade diese Lösung, aber das ist vermutlich Schwachsinn:
Code: Alles auswählen
class foo:
def __init__(self, data=('initial data','another'), oldfoo=None):
if oldfoo:
allmethods = [method for method in dir(oldfoo)]
for m in allmethods:
notclass = str(m).find('__') == -1 # isClassMethod?
if not callable(getattr(oldfoo, m)) and notclass:
setattr(self,m,(getattr(oldfoo,m)))
if data:
self.data = data
def __str__(self):
s = ''
for d in self.data: s+=' ' + str(d)
return s
if __name__=='__main__':
f = foo()
print 'f: ', f
g = foo(('new data','second'))
print 'g: ', g
h = foo('', g)
print 'h: ', h
Ich kann ja einfach self.data = oldfoo.data sagen. Dann muss ich allerdings sicherstellen, dass das Attribut existiert. Hintergrund ist, ich habe eine Klasse mit 30 Attributen. Sollte ich diese auch alle in ein Tupel packen?
Verfasst: Donnerstag 1. November 2007, 16:10
von BlackJack
Das sieht sehr kompliziert und fragil aus. Was willst Du überhaupt machen? Und muss das unbedingt in der `__init__()` passieren? Was spricht dagegen `copy.copy()` ausserhalb zu benutzen, oder in einer `copy()`-Methode auf dem Objekt oder zumindest eine Klassenmethode `from_foo()` oder so ähnlich bereit zu stellen!?
Verfasst: Freitag 2. November 2007, 14:51
von gecko
Hi,
danke für die Antwort.
Was ich eigentlich vorhabe ist das:
ich habe eine Reihe von States S_1, ..., S_N
Der State S_i zum Zeitpunkt i ergibt sich aus dem State zum Zeitpunkt i -1 (S_i-1) und der Beobachtung zum Zeitpunkt i (zusätzlichen Daten).
Jetzt habe ich gedacht, dass ich am besten bei der Erzeugung von S_i , S_i-1 mit auf den Weg gebe, aber das ist wie Du sagst keine gute Idee.
Das ganze verkompliziert sich noch, weil jeder State bis zu M alte States als Datenstruktur mitträgt. Nach M Zeitschritten wird der State auf 0 zurückgesetzt. Am besten wird wohl sein ich habe eine Klasse die alle States von 1 bis M enthält (Klasse Durchlauf) und eine Klasse wie bisher für jeden einzelnen State. Auf beiden Klassen will ich später komplexere Operationen ausführen (Bäume daraus erzeugen z.B.).