FAQ
I am writing a module 'caldict.py' with classes to manage 'timeline'
dictionaries. Timestamps (as strings) are lookup keys and the event data
they fetch is any string.
I am using Marc-Andr? Lemburg's mxDateTime package
http://starship.python.net/~lemburg/mxDateTime.html
plus 'seqdict' and 'mseqdict' modules by Wolfgang Grafen
http://home.germany.net/100-366919/Python/Modules/Modules.html
A great combination - thanks to both authors.

So far so good.
I have a class CalDict() which has various methods: init(), append(),
sort(), findnth(), etc..
I want to use key arguments for various options for all my functions in a
consistent manner.

import caldict
cd = caldict.CalDict()
cd.append(year55, month=4, day=5, hour, minute0, 'birthday')
cd.append(year= -2500, 'Bronze age')
cd.append(year = 1789, 'French Revolution')
cd.append(str(now()), 'here and now')
#now put everything in order beautifully thanks to seqdict and mxDateTime
cd.sort()
#Timeline events can be returned by date...
cd.getevent('1955-04-05 14:30:00.00')
#or by index...
cd.findnth(index='last')
cd.findnth(index=1)
cd.findnth(index= -2) #returns penultimate event ie: 'French Revolution'
#cool!
#now I need the option to have other arguments also for example:
cd.findnth(index='last', display=1)
#or
cd.findnth(index='last', showdate=1)

These will overide defaults and display the result, or show the date as well
as the event string for whatever the last item in the timeline is.

At present I do this very simply as follows inside class Caldict:

def reverse(self, display = 0):
s = self.eventdict
if display:
self.display()

But as I look down my list of growing class methods, I see the same code
repeated again and again.
There must be a much more elegant pythonic way to factor the "if display"
condition out. But not sure how..
I have a method display () in the top of my Class.but when I try to detect
there to see if the passed parameter display =1 it does not work.

I seem to be not undersrtanding something basic about passing parameters
and reusing methods within a class definition.

Another perhaps related problem also concernt best way to factor:

1 class Caldict:
2 def __init__(self, size, months=1, days=0, hours=0):
3 #default creates 12 months from the present day and time
4 self.eventdict = seqdict.seqdict()
5 self.indexdict = {}
6 s = self.eventdict
7 for x in range (size):
8 #initialize our delta values
9 dmonths = months * x
10 ddays = days * x
11 dhours = hours * x
12 ddate = now()+RelativeDateTime( months=+dmonths, days=+ddays,
hours=+dhours)
13 s.append(str(ddate), "entry" + str(x))
14 s.sort()
15 #showme
16 def display(self):
17 s = self.eventdict
18 if display:
19 for x in range(len(s)):
20 print x, s.keys()[x]

Why can do I have to redefine in line 17 's = self.eventdict' when I alrady
did so in line 6. Same for all teh followng methods?

This must be Python101..
I someone can help me get to grips with Python classes better..

Thanks
- Jason

________________________________________________________________
Jason CUNLIFFE = NOMADICS.(Interactive Art and Technology).Design Director

Search Discussions

  • Roeland Rengelink at Oct 2, 2000 at 9:48 am
    Hi Jason,

    A couple comments on your code, and, hopefully, some helpful
    explanation.

    Jason Cunliffe wrote:
    I am writing a module 'caldict.py' with classes to manage 'timeline'
    dictionaries. Timestamps (as strings) are lookup keys and the event data
    they fetch is any string.
    I am using Marc-Andr? Lemburg's mxDateTime package
    http://starship.python.net/~lemburg/mxDateTime.html
    plus 'seqdict' and 'mseqdict' modules by Wolfgang Grafen
    http://home.germany.net/100-366919/Python/Modules/Modules.html
    A great combination - thanks to both authors.

    So far so good.
    I have a class CalDict() which has various methods: init(), append(),
    sort(), findnth(), etc..
    I want to use key arguments for various options for all my functions in a
    consistent manner.

    import caldict
    cd = caldict.CalDict()
    cd.append(year55, month=4, day=5, hour, minute0, 'birthday')
    I'm surprised whis works. If I try something similar, I get
    SyntaxError: non-keyword arg after keyword arg
    I would expects the following to work correctly

    cd.append('birthday', year55, month=4, day=5, hour, minute0)

    provided your method definition is something like

    def append(event, year=0, month=0, day=0, hour, minute)

    cd.append(year= -2500, 'Bronze age')
    cd.append(year = 1789, 'French Revolution')
    cd.append(str(now()), 'here and now')
    #now put everything in order beautifully thanks to seqdict and mxDateTime
    cd.sort()
    #Timeline events can be returned by date...
    cd.getevent('1955-04-05 14:30:00.00')
    #or by index...
    cd.findnth(index='last')
    cd.findnth(index=1)
    cd.findnth(index= -2) #returns penultimate event ie: 'French Revolution'
    #cool!
    #now I need the option to have other arguments also for example:
    cd.findnth(index='last', display=1)
    #or
    cd.findnth(index='last', showdate=1)

    These will overide defaults and display the result, or show the date as well
    as the event string for whatever the last item in the timeline is.

    At present I do this very simply as follows inside class Caldict:

    def reverse(self, display = 0):
    s = self.eventdict
    if display:
    self.display()

    But as I look down my list of growing class methods, I see the same code
    repeated again and again.
    There must be a much more elegant pythonic way to factor the "if display"
    condition out. But not sure how..
    I have a method display () in the top of my Class.but when I try to detect
    there to see if the passed parameter display =1 it does not work.

    I seem to be not undersrtanding something basic about passing parameters
    and reusing methods within a class definition.

    Another perhaps related problem also concernt best way to factor:

    1 class Caldict:
    2 def __init__(self, size, months=1, days=0, hours=0):
    3 #default creates 12 months from the present day and time
    4 self.eventdict = seqdict.seqdict()
    5 self.indexdict = {}
    6 s = self.eventdict
    No need to this. You're just telling Python that you want to use s to
    refer to self.eventdict, but why not use self.eventdict to refer to
    self.eventdict
    7 for x in range (size):
    8 #initialize our delta values
    9 dmonths = months * x
    10 ddays = days * x
    11 dhours = hours * x
    12 ddate = now()+RelativeDateTime( months=+dmonths, days=+ddays,
    hours=+dhours)
    13 s.append(str(ddate), "entry" + str(x))
    14 s.sort()
    You can simply do
    self.eventdict.append(str(ddate), "entry" + str(x))
    self.eventdict.sort()
    15 #showme
    16 def display(self):
    17 s = self.eventdict
    18 if display:
    19 for x in range(len(s)):
    20 print x, s.keys()[x]

    Why can do I have to redefine in line 17 's = self.eventdict' when I alrady
    did so in line 6. Same for all teh followng methods?
    Well, the answer is that the s is in the local scope of both __init__()
    and display(), which means it is only defined within those functions,
    and Python forgets about it at soon as it returns from the function.
    But, as I said, you
    don't need s.
    This must be Python101..
    I someone can help me get to grips with Python classes better..
    OK.

    In Python names are references to objects. What this means is best shown
    by example.
    class A: # define a class object and name it A
    ... def do(self):
    ... print self
    ...
    A # What does A refer to?
    <class __main__.A at 80f76e0>
    A() # make an instance of A
    <__main__.A instance at 80e6668>
    a = A() # make another instance of A and name it a
    a # What does a refer to?
    <__main__.A instance at 80d91c8>
    a.do() # call a.do
    <__main__.A instance at 80d91c8>
    A.do(a) # a.do() == A.do(a)
    <__main__.A instance at
    80d91c8>
    A.do()
    Traceback (innermost last):
    File "<stdin>", line 1, in ?
    TypeError: unbound method must be called with class instance 1st
    argument

    So, whenever Python encounters a name it has to look up what that name
    refers
    to. To do that Python looks the name up in a dictionary. At any point in
    the program Python has access to two dictionaries, the global and the
    local
    dictionary (You can have a look at these using the build-in functions
    globals()
    and locals()) Each function has it's own local dictionary that is
    created when the function is called, and destroyed when the function
    returns.

    class A:
    ... def do(self, x):
    ... y = 1
    ... print locals()
    ...
    a = A()
    a.do('Hi')
    {'self': <__main__.A instance at 80f6a00>, 'x': 'Hi', 'y': 1}
    A.do(a, 'Ho')
    {'self': <__main__.A instance at 80f6a00>, 'x': 'Ho', 'y':
    1}

    Note how calling the method do() fills the locals() dictionary with the
    names
    self and and x. The rule for the name lookup is simple if the name is
    assigned to anywhere in the function look in the locals() dictionary,
    else look in the globals() dictionary.

    There are other places where references to objects are stored, in
    classes, instances and modules. There is a special syntax to refer to
    these dictionaries:
    class_name.__dict__, instance_name.__dict__, module_name.__dict__.
    Moreover, there is a convenient shorthand notation to refer to the
    contents of these dictionaries, namely:

    name.attrribute_name is shorthand for:
    name.__dict__[attribute_name],

    with the special rule that for retrieving references in instances:

    if instance_name.__dict__[attribute_name] raises a KeyError, then
    instance_name.__class__.__dict__[attribute_name] should be returned.

    To illustrate
    class A:
    ... x = 1 # A.__dict__['x'] = 1
    ... def do(self, y):
    ... self.y = y # self.__dict__['y'] = y
    ...
    a = A()
    a.__dict__
    {}
    a.do(2) # self=a ; self.__dict__['y'] = 2
    a.__dict__
    {'y': 2}
    A.__dict__
    {'__doc__': None, '__module__': '__main__', 'x': 1, 'do': <function do
    at 80d920
    a.__class__.__dict__
    {'__doc__': None, '__module__': '__main__', 'x': 1, 'do': <function do
    at 80d9208>}
    a.x # a.__dict__['x'] gives KeyError, return A.x
    1
    A.x = 3 # A.__dict__['x'] = 3
    a.x # a.__dict__['x'] still gives KeyError
    3
    a.x = 2 # a.__dict__['x'] = 2
    a.x
    2
    A.x # A.__dict__['x'] still contains 3
    3

    It should be clear now, why we pass a refrence to an instance to class
    methods.
    To give the methods access to the instance's dictionary. Note that
    classes don't know when they are instantiated (sp?), nor does the class
    method know which instance called it. In python the method has to be
    told explicitly which instance called it, hence the argument 'self'.
    The only convenience Python provides is
    that

    instance.method()

    is converted automatically in

    instance.__dict__['method'](instance)

    I hope you now understand why you don't have to do

    s = self.eventdict

    within each method.

    I also hope you understand why the display() method and the display=1
    method-argument are completely unrelated. One is a function object
    referred
    to in CalDict.__dict__ the other is a name in the locals()- dictionary
    of the findnth() method.

    Thanks
    - Jason

    ________________________________________________________________
    Jason CUNLIFFE = NOMADICS.(Interactive Art and Technology).Design Director
    Hope this help,

    Roeland
  • Roeland Rengelink at Oct 2, 2000 at 10:03 am
    Hi Jason,

    A couple comments on your code, and, hopefully, some helpful
    explanation.

    Jason Cunliffe wrote:
    I am writing a module 'caldict.py' with classes to manage 'timeline'
    dictionaries. Timestamps (as strings) are lookup keys and the event data
    they fetch is any string.
    I am using Marc-Andr? Lemburg's mxDateTime package
    http://starship.python.net/~lemburg/mxDateTime.html
    plus 'seqdict' and 'mseqdict' modules by Wolfgang Grafen
    http://home.germany.net/100-366919/Python/Modules/Modules.html
    A great combination - thanks to both authors.

    So far so good.
    I have a class CalDict() which has various methods: init(), append(),
    sort(), findnth(), etc..
    I want to use key arguments for various options for all my functions in a
    consistent manner.

    import caldict
    cd = caldict.CalDict()
    cd.append(year55, month=4, day=5, hour, minute0, 'birthday')
    I'm surprised whis works. If I try something similar, I get
    SyntaxError: non-keyword arg after keyword arg
    I would expects the following to work correctly

    cd.append('birthday', year55, month=4, day=5, hour, minute0)

    provided your method definition is something like

    def append(event, year=0, month=0, day=0, hour, minute)

    cd.append(year= -2500, 'Bronze age')
    cd.append(year = 1789, 'French Revolution')
    cd.append(str(now()), 'here and now')
    #now put everything in order beautifully thanks to seqdict and mxDateTime
    cd.sort()
    #Timeline events can be returned by date...
    cd.getevent('1955-04-05 14:30:00.00')
    #or by index...
    cd.findnth(index='last')
    cd.findnth(index=1)
    cd.findnth(index= -2) #returns penultimate event ie: 'French Revolution'
    #cool!
    #now I need the option to have other arguments also for example:
    cd.findnth(index='last', display=1)
    #or
    cd.findnth(index='last', showdate=1)

    These will overide defaults and display the result, or show the date as well
    as the event string for whatever the last item in the timeline is.

    At present I do this very simply as follows inside class Caldict:

    def reverse(self, display = 0):
    s = self.eventdict
    if display:
    self.display()

    But as I look down my list of growing class methods, I see the same code
    repeated again and again.
    There must be a much more elegant pythonic way to factor the "if display"
    condition out. But not sure how..
    I have a method display () in the top of my Class.but when I try to detect
    there to see if the passed parameter display =1 it does not work.

    I seem to be not undersrtanding something basic about passing parameters
    and reusing methods within a class definition.

    Another perhaps related problem also concernt best way to factor:

    1 class Caldict:
    2 def __init__(self, size, months=1, days=0, hours=0):
    3 #default creates 12 months from the present day and time
    4 self.eventdict = seqdict.seqdict()
    5 self.indexdict = {}
    6 s = self.eventdict
    No need to this. You're just telling Python that you want to use s to
    refer to self.eventdict, but why not use self.eventdict to refer to
    self.eventdict
    7 for x in range (size):
    8 #initialize our delta values
    9 dmonths = months * x
    10 ddays = days * x
    11 dhours = hours * x
    12 ddate = now()+RelativeDateTime( months=+dmonths, days=+ddays,
    hours=+dhours)
    13 s.append(str(ddate), "entry" + str(x))
    14 s.sort()
    You can simply do
    self.eventdict.append(str(ddate), "entry" + str(x))
    self.eventdict.sort()

    (you probably want to do it outside the loop)
    15 #showme
    16 def display(self):
    17 s = self.eventdict
    18 if display:
    19 for x in range(len(s)):
    20 print x, s.keys()[x]

    Why can do I have to redefine in line 17 's = self.eventdict' when I alrady
    did so in line 6. Same for all teh followng methods?
    Well, the answer is that the s is in the local scope of both __init__()
    and display(), which means it is only defined within those functions,
    and Python forgets about it at soon as it returns from the function.
    But, as I said, you
    don't need s.
    This must be Python101..
    I someone can help me get to grips with Python classes better..
    OK.

    In Python names are references to objects. What this means is best shown
    by example.
    class A: # define a class object and name it A
    ... def do(self):
    ... print self
    ...
    A # What does A refer to?
    <class __main__.A at 80f76e0>
    A() # make an instance of A
    <__main__.A instance at 80e6668>
    a = A() # make another instance of A and name it a
    a # What does a refer to?
    <__main__.A instance at 80d91c8>
    a.do() # call a.do
    <__main__.A instance at 80d91c8>
    A.do(a) # a.do() == A.do(a)
    <__main__.A instance at
    80d91c8>
    A.do()
    Traceback (innermost last):
    File "<stdin>", line 1, in ?
    TypeError: unbound method must be called with class instance 1st
    argument

    So, whenever Python encounters a name it has to look up what that name
    refers
    to. To do that Python looks the name up in a dictionary. At any point in
    the program Python has access to two dictionaries, the global and the
    local
    dictionary (You can have a look at these using the build-in functions
    globals()
    and locals()) Each function has it's own local dictionary that is
    created when the function is called, and destroyed when the function
    returns.

    class A:
    ... def do(self, x):
    ... y = 1
    ... print locals()
    ...
    a = A()
    a.do('Hi')
    {'self': <__main__.A instance at 80f6a00>, 'x': 'Hi', 'y': 1}
    A.do(a, 'Ho')
    {'self': <__main__.A instance at 80f6a00>, 'x': 'Ho', 'y':
    1}

    Note how calling the method do() fills the locals() dictionary with the
    names
    self and and x. The rule for the name lookup is simple if the name is
    assigned to anywhere in the function look in the locals() dictionary,
    else look in the globals() dictionary.

    There are other places where references to objects are stored, in
    classes, instances and modules. There is a special syntax to refer to
    these dictionaries:
    class_name.__dict__, instance_name.__dict__, module_name.__dict__.
    Moreover, there is a convenient shorthand notation to refer to the
    contents of these dictionaries, namely:

    name.attrribute_name is shorthand for:
    name.__dict__[attribute_name],

    with the special rule that for retrieving references in instances:

    if instance_name.__dict__[attribute_name] raises a KeyError, then
    instance_name.__class__.__dict__[attribute_name] should be returned.

    To illustrate
    class A:
    ... x = 1 # A.__dict__['x'] = 1
    ... def do(self, y):
    ... self.y = y # self.__dict__['y'] = y
    ...
    a = A()
    a.__dict__
    {}
    a.do(2) # self=a ; self.__dict__['y'] = 2
    a.__dict__
    {'y': 2}
    A.__dict__
    {'__doc__': None, '__module__': '__main__', 'x': 1, 'do': <function do
    at 80d920
    a.__class__.__dict__
    {'__doc__': None, '__module__': '__main__', 'x': 1, 'do': <function do
    at 80d9208>}
    a.x # a.__dict__['x'] gives KeyError, return A.x
    1
    A.x = 3 # A.__dict__['x'] = 3
    a.x # a.__dict__['x'] still gives KeyError
    3
    a.x = 2 # a.__dict__['x'] = 2
    a.x
    2
    A.x # A.__dict__['x'] still contains 3
    3

    It should be clear now, why we pass a refrence to an instance to class
    methods.
    To give the methods access to the instance's dictionary. Note that
    classes don't know when they are instantiated (sp?), nor does the class
    method know which instance called it. In python the method has to be
    told explicitly which instance called it, hence the argument 'self'.
    The only convenience Python provides is
    that

    instance.method()

    is converted automatically in

    instance.__dict__['method'](instance)

    I hope you now understand why you don't have to do

    s = self.eventdict

    within each method.

    I also hope you understand why the display() method and the display=1
    method-argument are completely unrelated. One is a function object
    referred
    to in CalDict.__dict__ the other is a name in the locals()- dictionary
    of the findnth() method.

    Thanks
    - Jason

    ________________________________________________________________
    Jason CUNLIFFE = NOMADICS.(Interactive Art and Technology).Design Director
    Hope this help,

    Roeland

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedOct 2, '00 at 12:54a
activeOct 2, '00 at 10:03a
posts3
users2
websitepython.org

People

Translate

site design / logo © 2022 Grokbase