How can I use __setitem__ method of dict object?

Discussion in 'Python' started by jeremito, Feb 6, 2007.

  1. jeremito

    jeremito Guest

    Please excuse me if this is obvious to others, but I can't figure it
    out. I am subclassing dict, but want to prevent direct changing of
    some key/value pairs. For this I thought I should override the
    __setitem__ method as such:


    class xs(dict):
    """
    XS is a container object to hold information about cross sections.
    """

    def __new__(cls, xS=1.0, xF=1.0, xG=1.0, nu=1.0, debug=0):
    """
    """
    x = {}
    x['xS'] = xS
    x['xF'] = xF
    x['nu'] = nu
    x['xG'] = xG
    x['xA'] = x['xG'] + x['xF']
    x['xT'] = x['xA'] + x['xS']

    return x

    def __setitem__(self, key, value):
    """
    I have overridden this method to prevent setting xT or xA
    outside the
    class.
    """
    print "I am in __setitem__"
    if key == 'xT':
    raise AttributeError("""Can't change xT. Please change,
    xF, xS, or xG""")


    But I can't even get __setitem__ to run. Example:
    Python 2.5 (r25:51918, Sep 19 2006, 08:49:13)
    [GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import xs
    >>> cs = xs.xs()
    >>> cs

    {'xA': 2.0, 'xF': 1.0, 'xG': 1.0, 'xS': 1.0, 'nu': 1.0, 'xT': 3.0}
    >>> cs['xT'] = 3.1415
    >>> cs

    {'xA': 2.0, 'xF': 1.0, 'xG': 1.0, 'xS': 1.0, 'nu': 1.0, 'xT':
    3.1415000000000002}


    Is this what the __setitem__ method is for? If not, how can I do what
    I want to do?
    Thanks in advance,
    Jeremy
    jeremito, Feb 6, 2007
    #1
    1. Advertising

  2. jeremito

    Steve Holden Guest

    jeremito wrote:
    > Please excuse me if this is obvious to others, but I can't figure it
    > out. I am subclassing dict, but want to prevent direct changing of
    > some key/value pairs. For this I thought I should override the
    > __setitem__ method as such:
    >
    >
    > class xs(dict):
    > """
    > XS is a container object to hold information about cross sections.
    > """
    >
    > def __new__(cls, xS=1.0, xF=1.0, xG=1.0, nu=1.0, debug=0):
    > """
    > """
    > x = {}
    > x['xS'] = xS
    > x['xF'] = xF
    > x['nu'] = nu
    > x['xG'] = xG
    > x['xA'] = x['xG'] + x['xF']
    > x['xT'] = x['xA'] + x['xS']
    >
    > return x
    >
    > def __setitem__(self, key, value):
    > """
    > I have overridden this method to prevent setting xT or xA
    > outside the
    > class.
    > """
    > print "I am in __setitem__"
    > if key == 'xT':
    > raise AttributeError("""Can't change xT. Please change,
    > xF, xS, or xG""")
    >
    >
    > But I can't even get __setitem__ to run. Example:
    > Python 2.5 (r25:51918, Sep 19 2006, 08:49:13)
    > [GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin
    > Type "help", "copyright", "credits" or "license" for more information.
    >>>> import xs
    >>>> cs = xs.xs()
    >>>> cs

    > {'xA': 2.0, 'xF': 1.0, 'xG': 1.0, 'xS': 1.0, 'nu': 1.0, 'xT': 3.0}
    >>>> cs['xT'] = 3.1415
    >>>> cs

    > {'xA': 2.0, 'xF': 1.0, 'xG': 1.0, 'xS': 1.0, 'nu': 1.0, 'xT':
    > 3.1415000000000002}
    >
    >
    > Is this what the __setitem__ method is for? If not, how can I do what
    > I want to do?


    >>> class d(dict):

    ... def __setitem__(self, k, v):
    ... print "Setting", k
    ... dict.__setitem__(self, k, v)
    ...
    >>> dd = d()
    >>> dd['steve'] = 'holden'

    Setting steve
    >>> dd['steve']

    'holden'
    >>>


    I believe the problem is that your __new__ method does not return an
    object of type xs but a dict, so it does not inherit the __getitem__
    method from xs but instead from dict.

    regards
    Steve
    --
    Steve Holden +44 150 684 7255 +1 800 494 3119
    Holden Web LLC/Ltd http://www.holdenweb.com
    Skype: holdenweb http://del.icio.us/steve.holden
    Blog of Note: http://holdenweb.blogspot.com
    See you at PyCon? http://us.pycon.org/TX2007
    Steve Holden, Feb 6, 2007
    #2
    1. Advertising

  3. jeremito

    Guest

    On 6 fév, 16:23, "jeremito" <> wrote:
    > Please excuse me if this is obvious to others, but I can't figure it
    > out. I am subclassing dict, but want to prevent direct changing of
    > some key/value pairs. For this I thought I should override the
    > __setitem__ method as such:
    >
    > class xs(dict):
    > """
    > XS is a container object to hold information about cross sections.
    > """
    >
    > def __new__(cls, xS=1.0, xF=1.0, xG=1.0, nu=1.0, debug=0):
    > """
    > """
    > x = {}
    > x['xS'] = xS
    > x['xF'] = xF
    > x['nu'] = nu
    > x['xG'] = xG
    > x['xA'] = x['xG'] + x['xF']
    > x['xT'] = x['xA'] + x['xS']
    >
    > return x


    replace this with:
    def __init__(self, xS=1.0, xF=1.0, xG=1.0, nu=1.0, debug=0):
    dict.__init__(
    self,
    xS=xS,
    xF=xF,
    xG=xG,
    nu=nu,
    xA=xG + xF,
    xT=xG + xF + xS
    )

    > def __setitem__(self, key, value):
    > """
    > I have overridden this method to prevent setting xT or xA
    > outside the
    > class.
    > """
    > print "I am in __setitem__"
    > if key == 'xT':
    > raise AttributeError(

    "Can't change xT. Please change, xF, xS, or xG"
    )
    dict.__setitem__(self, key, value)

    > But I can't even get __setitem__ to run.


    of course, since your __new__ method returns a dict instance, not a xs
    instance...
    There are very few cases where you really need to override the __new__
    method.

    > Example:
    > Python 2.5 (r25:51918, Sep 19 2006, 08:49:13)
    > [GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin
    > Type "help", "copyright", "credits" or "license" for more information.>>> import xs
    > >>> cs = xs.xs()
    > >>> cs

    >
    > {'xA': 2.0, 'xF': 1.0, 'xG': 1.0, 'xS': 1.0, 'nu': 1.0, 'xT': 3.0}>>> cs['xT'] = 3.1415
    > >>> cs

    >
    > {'xA': 2.0, 'xF': 1.0, 'xG': 1.0, 'xS': 1.0, 'nu': 1.0, 'xT':
    > 3.1415000000000002}
    >
    > Is this what the __setitem__ method is for?


    Yes. But note that you you need to manually call the superclass's
    overriden method - unless you
    really want to replace it with your own, which is obviously not the
    case here...

    Note that if someone manually changes the values of xG, xF, or xS, the
    computed values of xA and/or xT
    won't reflect this change. Is that what you want ?

    Finally, and if I may ask, what is your use-case for subclassing
    dict ? You don't need this to implement a dict-like object,
    and it might be simpler in your case to write an ordinary class, then
    add support for the required subset of the dict interface.

    My 2 cents...
    , Feb 6, 2007
    #3
  4. jeremito

    jeremito Guest

    On Feb 6, 10:59 am, ""
    <> wrote:
    > On 6 fév, 16:23, "jeremito" <> wrote:
    >
    >
    >
    > > Please excuse me if this is obvious to others, but I can't figure it
    > > out. I am subclassing dict, but want to prevent direct changing of
    > > some key/value pairs. For this I thought I should override the
    > > __setitem__ method as such:

    >
    > > class xs(dict):
    > > """
    > > XS is a container object to hold information about cross sections.
    > > """

    >
    > > def __new__(cls, xS=1.0, xF=1.0, xG=1.0, nu=1.0, debug=0):
    > > """
    > > """
    > > x = {}
    > > x['xS'] = xS
    > > x['xF'] = xF
    > > x['nu'] = nu
    > > x['xG'] = xG
    > > x['xA'] = x['xG'] + x['xF']
    > > x['xT'] = x['xA'] + x['xS']

    >
    > > return x

    >
    > replace this with:
    > def __init__(self, xS=1.0, xF=1.0, xG=1.0, nu=1.0, debug=0):
    > dict.__init__(
    > self,
    > xS=xS,
    > xF=xF,
    > xG=xG,
    > nu=nu,
    > xA=xG + xF,
    > xT=xG + xF + xS
    > )
    >
    > > def __setitem__(self, key, value):
    > > """
    > > I have overridden this method to prevent setting xT or xA
    > > outside the
    > > class.
    > > """
    > > print "I am in __setitem__"
    > > if key == 'xT':
    > > raise AttributeError(

    >
    > "Can't change xT. Please change, xF, xS, or xG"
    > )
    > dict.__setitem__(self, key, value)
    >
    > > But I can't even get __setitem__ to run.

    >
    > of course, since your __new__ method returns a dict instance, not a xs
    > instance...
    > There are very few cases where you really need to override the __new__
    > method.


    The reason I create my object with __new__ instead of __init__ is
    because when I use __init__ when a value is set it calls __setitem__.
    This is what I want to happen, but not inside of __init__. Does this
    make sense? I'm sure there is a better/more pythonic way to do this,
    but I'm unsure of what it is. Can someone show me an example of how
    this should work?


    >
    > > Example:
    > > Python 2.5 (r25:51918, Sep 19 2006, 08:49:13)
    > > [GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin
    > > Type "help", "copyright", "credits" or "license" for more information.>>> import xs
    > > >>> cs = xs.xs()
    > > >>> cs

    >
    > > {'xA': 2.0, 'xF': 1.0, 'xG': 1.0, 'xS': 1.0, 'nu': 1.0, 'xT': 3.0}>>> cs['xT'] = 3.1415
    > > >>> cs

    >
    > > {'xA': 2.0, 'xF': 1.0, 'xG': 1.0, 'xS': 1.0, 'nu': 1.0, 'xT':
    > > 3.1415000000000002}

    >
    > > Is this what the __setitem__ method is for?

    >
    > Yes. But note that you you need to manually call the superclass's
    > overriden method - unless you
    > really want to replace it with your own, which is obviously not the
    > case here...
    >
    > Note that if someone manually changes the values of xG, xF, or xS, the
    > computed values of xA and/or xT
    > won't reflect this change. Is that what you want ?
    >


    Eventually (when I figure out how to use __setitem__) I will change
    what happens when xG, xF, or xS are changed so that it also changes xA
    and xT.

    > Finally, and if I may ask, what is your use-case for subclassing
    > dict ? You don't need this to implement a dict-like object,
    > and it might be simpler in your case to write an ordinary class, then
    > add support for the required subset of the dict interface.


    Eventually I am going to add other features to my class (as I have
    mentioned) so I can't simply use a dict object.

    >
    > My 2 cents...


    Thanks again,
    Jeremy
    jeremito, Feb 6, 2007
    #4
  5. "jeremito" <> escribió en el mensaje
    news:...

    > Please excuse me if this is obvious to others, but I can't figure it
    > out. I am subclassing dict, but want to prevent direct changing of
    > some key/value pairs. For this I thought I should override the
    > __setitem__ method as such:
    > if key == 'xT':
    > raise AttributeError("""Can't change xT. Please change,
    > xF, xS, or xG""")


    Why using a dictionary? I'd use a simple class with properties:

    py> class Xs(object): # class names should be Uppercase
    .... def __init__(self, xS=1.0, xF=1.0, xG=1.0, nu=1.0, debug=0):
    .... self.xS = xS
    .... self.xF = xF
    .... self.nu = nu
    .... self.xG = xG
    .... xA = property(fget=lambda self: self.xG + self.xF)
    .... xT = property(fget=lambda self: self.xA + self.xS)
    ....
    py> xs = Xs(1.0, 0.95, 0.80, 0.70)
    py> print xs.xG
    0.8
    py> print xs.xA
    1.75
    py> print xs.xT
    2.75
    py> xs.xG = 0.5
    py> print xs.xA
    1.45
    py> print xs.xT
    2.45
    py> xs.xA = 1.5
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    AttributeError: can't set attribute
    py> xs.xT = 1.2
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    AttributeError: can't set attribute
    py>

    --
    Gabriel Genellina
    Gabriel Genellina, Feb 6, 2007
    #5
  6. jeremito a écrit :
    > On Feb 6, 10:59 am, ""
    > <> wrote:
    >
    >>On 6 fév, 16:23, "jeremito" <> wrote:
    >>

    (snip)
    >>>But I can't even get __setitem__ to run.

    >>
    >>of course, since your __new__ method returns a dict instance, not a xs
    >>instance...
    >>There are very few cases where you really need to override the __new__
    >>method.

    >
    >
    > The reason I create my object with __new__ instead of __init__ is
    > because when I use __init__ when a value is set it calls __setitem__.
    > This is what I want to happen, but not inside of __init__. Does this
    > make sense?


    It would make sens - if you couldn't call dict.__setitem__ directly.

    > I'm sure there is a better/more pythonic way to do this,
    > but I'm unsure of what it is. Can someone show me an example of how
    > this should work?
    >
    >

    (snip)
    >>>Is this what the __setitem__ method is for?

    >>
    >>Yes. But note that you you need to manually call the superclass's
    >>overriden method - unless you
    >>really want to replace it with your own, which is obviously not the
    >>case here...
    >>
    >>Note that if someone manually changes the values of xG, xF, or xS, the
    >>computed values of xA and/or xT
    >>won't reflect this change. Is that what you want ?
    >>

    >
    >
    > Eventually (when I figure out how to use __setitem__) I will change
    > what happens when xG, xF, or xS are changed so that it also changes xA
    > and xT.


    Which is not the best way to go IMHO. Unless the computation is very
    intensive (which doesn't seem to be the case here) or it's heavily used
    in big loops *and* the perfs are not good enough, it's better to
    recompute on the fly at read time. And if one of the above cases arises,
    then it will be time to use memoization (ie: cache the result of
    computation, invalidating the cache when needed).

    >
    >>Finally, and if I may ask, what is your use-case for subclassing
    >>dict ? You don't need this to implement a dict-like object,
    >>and it might be simpler in your case to write an ordinary class, then
    >>add support for the required subset of the dict interface.

    >
    >
    > Eventually I am going to add other features to my class (as I have
    > mentioned) so I can't simply use a dict object.


    I already understood this. My question is : why do you want to
    *subclass* dict. In Python, inheritence is only about implementation,
    it's *not* needed for polymorphism to work. So you don't have to
    subclass dict to have an object behaving (more or less, that's up to
    you) like a dict.

    Here's an alternative implementation, so you get the idea. Note that it
    behaves mostly like a dict (well, not totally, but since we don't know
    which subset of the dict interface you need...), but also like a
    'standard' object, so you can use either cs.['xT'] or cs.xT with the
    same result.

    class Xs(dict):
    """
    Xs is a container object to hold information about cross sections.
    """
    _computedkeys = 'xA', 'xT'

    def __init__(self, xS=1.0, xF=1.0, xG=1.0, nu=1.0, debug=0):
    self.xS = xS
    self.xF = xF
    self.xG = xG
    self.nu = nu

    # xA and xT as properties (AKA computed attributes)
    def _get_xA(self):
    return self.xG + self.xF
    def _set_xA(self, dummy):
    raise AttributeError(
    "%s.xA is read-only" % self.__class__.__name__
    )
    xA = property(fset=_set_xA, fget=_get_xA)

    def _get_xT(self):
    return self.xA + self.xS
    def _set_xT(self, dummy):
    raise AttributeError(
    "%s.xT is read-only" % self.__class__.__name__
    )
    xT = property(fset=_set_xT, fget=_get_xT)

    # dict interface support, to be extended if needed
    def __setitem__(self, key, value):
    setattr(self, key, value)

    def __getitem__(self, key):
    return getattr(self, key)

    def keys(self):
    return self.__dict__.keys() + list(self._computedkeys)

    def values(self):
    return self.__dict__.values() \
    + [getattr(self, key) for key in self._computedkeys]

    def items(self):
    return zip(self.keys(), self.values())

    def __iter__(self):
    for k in self.keys():
    yield k
    raise StopIteration

    def __contains__(self, key):
    return key in self.keys()

    def __repr__(self):
    return repr(dict(self.items()))
    Bruno Desthuilliers, Feb 6, 2007
    #6
  7. jeremito

    jeremito Guest

    On Feb 6, 2:36 pm, Bruno Desthuilliers
    <> wrote:
    > jeremito a écrit :
    >
    >
    >
    > > On Feb 6, 10:59 am, ""
    > > <> wrote:

    >
    > >>On 6 fév, 16:23, "jeremito" <> wrote:

    >
    > (snip)
    > >>>But I can't even get __setitem__ to run.

    >
    > >>of course, since your __new__ method returns a dict instance, not a xs
    > >>instance...
    > >>There are very few cases where you really need to override the __new__
    > >>method.

    >
    > > The reason I create my object with __new__ instead of __init__ is
    > > because when I use __init__ when a value is set it calls __setitem__.
    > > This is what I want to happen, but not inside of __init__. Does this
    > > make sense?

    >
    > It would make sens - if you couldn't call dict.__setitem__ directly.
    >
    >
    >
    >
    >
    > > I'm sure there is a better/more pythonic way to do this,
    > > but I'm unsure of what it is. Can someone show me an example of how
    > > this should work?

    >
    > (snip)
    > >>>Is this what the __setitem__ method is for?

    >
    > >>Yes. But note that you you need to manually call the superclass's
    > >>overriden method - unless you
    > >>really want to replace it with your own, which is obviously not the
    > >>case here...

    >
    > >>Note that if someone manually changes the values of xG, xF, or xS, the
    > >>computed values of xA and/or xT
    > >>won't reflect this change. Is that what you want ?

    >
    > > Eventually (when I figure out how to use __setitem__) I will change
    > > what happens when xG, xF, or xS are changed so that it also changes xA
    > > and xT.

    >
    > Which is not the best way to go IMHO. Unless the computation is very
    > intensive (which doesn't seem to be the case here) or it's heavily used
    > in big loops *and* the perfs are not good enough, it's better to
    > recompute on the fly at read time. And if one of the above cases arises,
    > then it will be time to use memoization (ie: cache the result of
    > computation, invalidating the cache when needed).
    >
    >
    >
    > >>Finally, and if I may ask, what is your use-case for subclassing
    > >>dict ? You don't need this to implement a dict-like object,
    > >>and it might be simpler in your case to write an ordinary class, then
    > >>add support for the required subset of the dict interface.

    >
    > > Eventually I am going to add other features to my class (as I have
    > > mentioned) so I can't simply use a dict object.

    >
    > I already understood this. My question is : why do you want to
    > *subclass* dict. In Python, inheritence is only about implementation,
    > it's *not* needed for polymorphism to work. So you don't have to
    > subclass dict to have an object behaving (more or less, that's up to
    > you) like a dict.
    >
    > Here's an alternative implementation, so you get the idea. Note that it
    > behaves mostly like a dict (well, not totally, but since we don't know
    > which subset of the dict interface you need...), but also like a
    > 'standard' object, so you can use either cs.['xT'] or cs.xT with the
    > same result.
    >
    > class Xs(dict):
    > """
    > Xs is a container object to hold information about cross sections.
    > """
    > _computedkeys = 'xA', 'xT'
    >
    > def __init__(self, xS=1.0, xF=1.0, xG=1.0, nu=1.0, debug=0):
    > self.xS = xS
    > self.xF = xF
    > self.xG = xG
    > self.nu = nu
    >
    > # xA and xT as properties (AKA computed attributes)
    > def _get_xA(self):
    > return self.xG + self.xF
    > def _set_xA(self, dummy):
    > raise AttributeError(
    > "%s.xA is read-only" % self.__class__.__name__
    > )
    > xA = property(fset=_set_xA, fget=_get_xA)
    >
    > def _get_xT(self):
    > return self.xA + self.xS
    > def _set_xT(self, dummy):
    > raise AttributeError(
    > "%s.xT is read-only" % self.__class__.__name__
    > )
    > xT = property(fset=_set_xT, fget=_get_xT)
    >
    > # dict interface support, to be extended if needed
    > def __setitem__(self, key, value):
    > setattr(self, key, value)
    >
    > def __getitem__(self, key):
    > return getattr(self, key)
    >
    > def keys(self):
    > return self.__dict__.keys() + list(self._computedkeys)
    >
    > def values(self):
    > return self.__dict__.values() \
    > + [getattr(self, key) for key in self._computedkeys]
    >
    > def items(self):
    > return zip(self.keys(), self.values())
    >
    > def __iter__(self):
    > for k in self.keys():
    > yield k
    > raise StopIteration
    >
    > def __contains__(self, key):
    > return key in self.keys()
    >
    > def __repr__(self):
    > return repr(dict(self.items()))


    Thanks a lot for your help. I think what you have written is much
    better than what I could have come up with on my own. I guess I just
    need more experience.
    Thanks,
    Jeremy
    jeremito, Feb 6, 2007
    #7
  8. jeremito a écrit :
    > On Feb 6, 2:36 pm, Bruno Desthuilliers
    > <> wrote:
    >

    (snip)

    >>Here's an alternative implementation, so you get the idea.
    >>
    >>class Xs(dict):


    oops ! I meant:
    class Xs(object):

    of course...

    (snip)
    > I guess I just
    > need more experience.


    Possibly - but not only. You may want to have a look at the
    FineManual(tm) for all this kind of "magic", starting with :
    http://docs.python.org/ref/specialnames.html
    http://docs.python.org/ref/sequence-types.html

    HTH
    Bruno Desthuilliers, Feb 6, 2007
    #8
  9. jeremito

    jeremito Guest

    On Feb 6, 5:10 pm, Bruno Desthuilliers
    <> wrote:
    > jeremito a écrit :
    > > On Feb 6, 2:36 pm, Bruno Desthuilliers > <> wrote:

    >
    > >

    > (snip)
    >
    > >>Here's an alternative implementation, so you get the idea.
    > >>
    > >>class Xs(dict):

    >
    > oops ! I meant:
    > class Xs(object):
    >
    > of course...
    >
    > (snip)
    >
    > > I guess I just
    > > need more experience.

    >
    > Possibly - but not only. You may want to have a look at the
    > FineManual(tm) for all this kind of "magic", starting with :http://docs.python.org/ref/specialnames.htmlhttp://docs.python.org/ref/sequence-types.html
    >
    > HTH


    Thanks again! Sometimes the problem is simply not knowing where to
    find the documentation, or finding the right portion of the
    documentation. Your help has been invaluable.

    Jeremy
    jeremito, Feb 7, 2007
    #9
  10. jeremito

    jeremito Guest

    On Feb 7, 8:28 am, "jeremito" <> wrote:
    > On Feb 6, 5:10 pm, Bruno Desthuilliers
    >
    >
    >
    > <> wrote:
    > > jeremito a écrit :
    > > > On Feb 6, 2:36 pm, Bruno Desthuilliers > <> wrote:

    >
    > > (snip)

    >
    > > >>Here's an alternative implementation, so you get the idea.

    >
    > > >>class Xs(dict):

    >
    > > oops ! I meant:
    > > class Xs(object):

    >
    > > of course...

    >
    > > (snip)

    >
    > > > I guess I just
    > > > need more experience.

    >
    > > Possibly - but not only. You may want to have a look at the
    > > FineManual(tm) for all this kind of "magic", starting with :http://docs..python.org/ref/specialnames.htmlhttp://docs.python.org/re...

    >
    > > HTH

    >
    > Thanks again! Sometimes the problem is simply not knowing where to
    > find the documentation, or finding the right portion of the
    > documentation. Your help has been invaluable.
    >
    > Jeremy


    One more question. I will be asking for the value of cs.xT *many*
    (~millions) times. Therefore I don't want it's value to be calculated
    on the fly. How can I set the value of xT whenever xS, xF, or xG are
    changed, but not allow it to be set directly? From the example given
    previously, it seems like it can't be done this way.

    Thans,
    Jeremy
    jeremito, Feb 7, 2007
    #10
  11. jeremito kirjoitti:
    > On Feb 7, 8:28 am, "jeremito" <> wrote:
    >> On Feb 6, 5:10 pm, Bruno Desthuilliers
    >>
    >>
    >>
    >> <> wrote:
    >>> jeremito a écrit :
    >>> > On Feb 6, 2:36 pm, Bruno Desthuilliers > <> wrote:
    >>> (snip)
    >>> >>Here's an alternative implementation, so you get the idea.
    >>> >>class Xs(dict):
    >>> oops ! I meant:
    >>> class Xs(object):
    >>> of course...
    >>> (snip)
    >>>> I guess I just
    >>>> need more experience.
    >>> Possibly - but not only. You may want to have a look at the
    >>> FineManual(tm) for all this kind of "magic", starting with :http://docs.python.org/ref/specialnames.htmlhttp://docs.python.org/re...
    >>> HTH

    >> Thanks again! Sometimes the problem is simply not knowing where to
    >> find the documentation, or finding the right portion of the
    >> documentation. Your help has been invaluable.
    >>
    >> Jeremy

    >
    > One more question. I will be asking for the value of cs.xT *many*
    > (~millions) times. Therefore I don't want it's value to be calculated
    > on the fly. How can I set the value of xT whenever xS, xF, or xG are
    > changed, but not allow it to be set directly? From the example given
    > previously, it seems like it can't be done this way.
    >
    > Thans,
    > Jeremy
    >

    I'm certainly no wizard in timing, but here goes:

    Using the class definition given to you by Bruno, adding the following
    to the end (and 'import timeit' at the start):

    #============
    lst = timeit.Timer('for i in xrange(10): xx=xs.xT', \
    'from __main__ import Xs;xs = Xs()').repeat(100,1000)
    lst.sort()
    print lst
    print 'Average:', sum(lst)/100
    #============

    I get the output:
    [0.017246605364648282, 0.01727426251101738, 0.017275659336591698,
    0.017290745052793044, 0.01733264982001903, 0.017347735536220377,

    and so on ...

    0.029063749722380933, 0.029163762433493667, 0.029422733894950315,
    0.029790378386079785]
    Average: 0.0182474979362

    Thus: A 1000 assignments take a little over 18 milliseconds. The largest
    values in the list are probably caused bu GC occurring. But even 30 ms /
    1000 iterations i.e. 30 microseconds per fetch seems to be fast enough.

    All this depends of course on the computer used. Mine is on the fast
    side, you might test it on your PC.

    The correct way of programming is to find a good simple algorithm and
    the data structures needed, to program a clean solution with them and
    then when you've got a correctly operating application and THEN IF you
    need speed try to do something about it.

    "Premature optimization is the worst evil" or something like that is how
    the saying goes.

    Hopefully I'm not leading you astray by being a novice in using the
    timeit module.


    HTH,
    Jussi
    Jussi Salmela, Feb 7, 2007
    #11
  12. jeremito

    jeremito Guest

    On Feb 7, 12:48 pm, Jussi Salmela <> wrote:
    > jeremito kirjoitti:
    >
    > > On Feb 7, 8:28 am, "jeremito" <> wrote:
    > >> On Feb 6, 5:10 pm, Bruno Desthuilliers

    >
    > >> <> wrote:
    > >>> jeremito a écrit :
    > >>> > On Feb 6, 2:36 pm, Bruno Desthuilliers > <bdesth.quelquech...@free..quelquepart.fr> wrote:
    > >>> (snip)
    > >>> >>Here's an alternative implementation, so you get the idea.
    > >>> >>class Xs(dict):
    > >>> oops ! I meant:
    > >>> class Xs(object):
    > >>> of course...
    > >>> (snip)
    > >>>> I guess I just
    > >>>> need more experience.
    > >>> Possibly - but not only. You may want to have a look at the
    > >>> FineManual(tm) for all this kind of "magic", starting with :http://docs.python.org/ref/specialnames.htmlhttp://docs.python.org/re...
    > >>> HTH
    > >> Thanks again! Sometimes the problem is simply not knowing where to
    > >> find the documentation, or finding the right portion of the
    > >> documentation. Your help has been invaluable.

    >
    > >> Jeremy

    >
    > > One more question. I will be asking for the value of cs.xT *many*
    > > (~millions) times. Therefore I don't want it's value to be calculated
    > > on the fly. How can I set the value of xT whenever xS, xF, or xG are
    > > changed, but not allow it to be set directly? From the example given
    > > previously, it seems like it can't be done this way.

    >
    > > Thans,
    > > Jeremy

    >
    > I'm certainly no wizard in timing, but here goes:
    >
    > Using the class definition given to you by Bruno, adding the following
    > to the end (and 'import timeit' at the start):
    >
    > #============
    > lst = timeit.Timer('for i in xrange(10): xx=xs.xT', \
    > 'from __main__ import Xs;xs = Xs()').repeat(100,1000)
    > lst.sort()
    > print lst
    > print 'Average:', sum(lst)/100
    > #============
    >
    > I get the output:
    > [0.017246605364648282, 0.01727426251101738, 0.017275659336591698,
    > 0.017290745052793044, 0.01733264982001903, 0.017347735536220377,
    >
    > and so on ...
    >
    > 0.029063749722380933, 0.029163762433493667, 0.029422733894950315,
    > 0.029790378386079785]
    > Average: 0.0182474979362
    >
    > Thus: A 1000 assignments take a little over 18 milliseconds. The largest
    > values in the list are probably caused bu GC occurring. But even 30 ms /
    > 1000 iterations i.e. 30 microseconds per fetch seems to be fast enough.
    >
    > All this depends of course on the computer used. Mine is on the fast
    > side, you might test it on your PC.
    >
    > The correct way of programming is to find a good simple algorithm and
    > the data structures needed, to program a clean solution with them and
    > then when you've got a correctly operating application and THEN IF you
    > need speed try to do something about it.
    >
    > "Premature optimization is the worst evil" or something like that is how
    > the saying goes.
    >
    > Hopefully I'm not leading you astray by being a novice in using the
    > timeit module.
    >
    > HTH,
    > Jussi


    Thank you. Once again this mailing list has proven most helpful. I
    realize it probably isn't worth my time (or stress) to figure out how
    to avoid calculating xT on the fly-at least not yet.

    Jeremy
    jeremito, Feb 7, 2007
    #12
  13. jeremito a écrit :
    (snip)
    >>
    >>Thanks again! Sometimes the problem is simply not knowing where to
    >>find the documentation,


    http://python.org/doc is usually a good start !-)

    >>or finding the right portion of the
    >>documentation.


    Yes, this is not always obvious. FWIW, browsing docs is probably the
    most time-consuming task of programmers.

    > One more question. I will be asking for the value of cs.xT *many*
    > (~millions) times. Therefore I don't want it's value to be calculated
    > on the fly.


    As Jussi said, first make it right. And then, *if* you have a *real*
    performance problem, profile your code to find where bottlenecks really are.

    > How can I set the value of xT whenever xS, xF, or xG are
    > changed, but not allow it to be set directly? From the example given
    > previously, it seems like it can't be done this way.


    A naive solution might be to turn all these attributes into properties,
    so you could recompute and store the values of xA and xT each time xS,
    xF or xG are modified. The example I gave you should be enough to get
    you started here. But beware: in Python, function calls are somewhat
    expansive, so you may end up slowing down your code.

    Once again, first focus on cleanly solving the problem, and if *and only
    if* you have objective performance problems, then *profile* your code
    before trying to solve the wrong problem.
    Bruno Desthuilliers, Feb 7, 2007
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ron Garret

    Setdefault bypasses __setitem__

    Ron Garret, Oct 13, 2005, in forum: Python
    Replies:
    9
    Views:
    467
    Fredrik Lundh
    Oct 14, 2005
  2. Almad
    Replies:
    8
    Views:
    396
    Terry Reedy
    Dec 14, 2006
  3. Tor Erik Soenvisen

    str and __setitem__

    Tor Erik Soenvisen, Jan 25, 2007, in forum: Python
    Replies:
    3
    Views:
    271
  4. Spencer Pearson

    Instances' __setitem__ methods

    Spencer Pearson, Jun 21, 2011, in forum: Python
    Replies:
    2
    Views:
    222
    Chris Rebert
    Jun 21, 2011
  5. luvspython
    Replies:
    2
    Views:
    410
    Eric Snow
    Aug 19, 2011
Loading...

Share This Page