pass object or use self.object?

Discussion in 'Python' started by Tim Arnold, Apr 6, 2010.

  1. Tim Arnold

    Tim Arnold Guest

    Hi,
    I have a few classes that manipulate documents. One is really a
    process that I use a class for just to bundle a bunch of functions
    together (and to keep my call signatures the same for each of my
    manipulator classes).

    So my question is whether it's bad practice to set things up so each
    method operates on self.document or should I pass document around from
    one function to the next?
    pseudo code:

    class ManipulatorA(object):
    def process(self, document):
    document = self.do_one_thing(document)
    document = self.do_another_thing(document)
    # bunch of similar lines
    return document

    or

    class ManipulatorA(object):
    def process(self, document):
    self.document = document
    self.do_one_thing() # operates on self.document
    self.do_another_thing()
    # bunch of similar lines
    return self.document

    I ask because I've been told that the first case is easier to
    understand. I never thought of it before, so I'd appreciate any
    comments.
    thanks,
    --Tim
    Tim Arnold, Apr 6, 2010
    #1
    1. Advertising

  2. Tim Arnold a écrit :
    > Hi,
    > I have a few classes that manipulate documents. One is really a
    > process that I use a class for just to bundle a bunch of functions
    > together (and to keep my call signatures the same for each of my
    > manipulator classes).
    >
    > So my question is whether it's bad practice to set things up so each
    > method operates on self.document or should I pass document around from
    > one function to the next?


    As far as I'm concerned, I strongly prefer passing the document around.
    Makes thing clear, avoids useless preconditions (is self.document set
    ???) and race conditions (if two threads have to share the Manipulator
    instance), makes the code easier to understand / maintain / refactor IMHO.

    Also remember that modules are objects too, so - depending on parts of
    your code we don't see here - you may even maintain your API without
    having to use a "class as module".

    My 2 cents
    Bruno Desthuilliers, Apr 6, 2010
    #2
    1. Advertising

  3. Tim Arnold wrote:
    > Hi,
    > I have a few classes that manipulate documents. One is really a
    > process that I use a class for just to bundle a bunch of functions
    > together (and to keep my call signatures the same for each of my
    > manipulator classes).
    >
    > So my question is whether it's bad practice to set things up so each
    > method operates on self.document or should I pass document around from
    > one function to the next?
    > pseudo code:
    >
    > class ManipulatorA(object):
    > def process(self, document):
    > document = self.do_one_thing(document)
    > document = self.do_another_thing(document)
    > # bunch of similar lines
    > return document
    >
    > or
    >
    > class ManipulatorA(object):
    > def process(self, document):
    > self.document = document
    > self.do_one_thing() # operates on self.document
    > self.do_another_thing()
    > # bunch of similar lines
    > return self.document
    >
    > I ask because I've been told that the first case is easier to
    > understand. I never thought of it before, so I'd appreciate any
    > comments.
    > thanks,
    > --Tim
    >

    Usually, when using classes as namespace, functions are declared as
    static (or as classmethod if required).
    e.g.


    class Foo:
    @classmethod
    def process(cls, document):
    print 'process of'
    cls.foo(document)

    @staticmethod
    def foo(document):
    print document

    In [5]: Foo.process('my document')
    process of
    my document


    There is no more question about self, 'cause there is no more self. You
    don't need to create any instance of Foo neither.

    JM
    Jean-Michel Pichavant, Apr 6, 2010
    #3
  4. Tim Arnold

    Lie Ryan Guest

    On 04/06/10 23:52, Tim Arnold wrote:
    > Hi,
    > I have a few classes that manipulate documents. One is really a
    > process that I use a class for just to bundle a bunch of functions
    > together (and to keep my call signatures the same for each of my
    > manipulator classes).
    >
    > So my question is whether it's bad practice to set things up so each
    > method operates on self.document or should I pass document around from
    > one function to the next?
    > pseudo code:
    >
    > class ManipulatorA(object):
    > def process(self, document):
    > document = self.do_one_thing(document)
    > document = self.do_another_thing(document)
    > # bunch of similar lines
    > return document
    >
    > or
    >
    > class ManipulatorA(object):
    > def process(self, document):
    > self.document = document
    > self.do_one_thing() # operates on self.document
    > self.do_another_thing()
    > # bunch of similar lines
    > return self.document


    Since in function in python is a first-class object, you can instead do
    something like:

    def process(document):
    # note: document should encapsulate its own logic
    document.do_one_thing()
    document.do_another_thing()

    And when you need some complex logic, you can easily elevate your
    function to a class:

    class Appender(object):
    def __init__(self, text):
    self.text = text
    def __call__(self, document):
    mtext = self.manipulate(document, text)
    document.append(mtext)

    and I think for your purpose, the mixin pattern could cleanly separate
    manipulation and document while still obeying object-oriented pattern
    that document is self-sufficient:

    # language with only single-inheritance can only dream to do this
    class Appendable(object):
    def append(self, text):
    self.text += text
    class Savable(object):
    def save(self, fileobj):
    fileobj.write(self.text)
    class Openable(object):
    def open(self, fileobj):
    self.text = fileobj.read()
    class Document(Appendable, Savable, Openable):
    def __init__(self):
    self.text = ''
    Lie Ryan, Apr 6, 2010
    #4
  5. Lie Ryan a écrit :
    (snip)

    > Since in function in python is a first-class object, you can instead do
    > something like:
    >
    > def process(document):
    > # note: document should encapsulate its own logic
    > document.do_one_thing()


    Obvious case of encapsulation abuse here. Should a file object
    encapsulate all the csv parsing logic ? (and the html parsing, xml
    parsing, image manipulation etc...) ? Should a "model" object
    encapsulate the presentation logic ? I could go on for hours here...

    >
    > and I think for your purpose, the mixin pattern could cleanly separate
    > manipulation and document while still obeying object-oriented pattern
    > that document is self-sufficient:
    >
    > # language with only single-inheritance can only dream to do this
    >
    > class Appendable(object):
    > def append(self, text):
    > self.text += text
    > class Savable(object):
    > def save(self, fileobj):
    > fileobj.write(self.text)
    > class Openable(object):
    > def open(self, fileobj):
    > self.text = fileobj.read()
    > class Document(Appendable, Savable, Openable):
    > def __init__(self):
    > self.text = ''


    Anyone having enough experience with Zope2 knows why this sucks big time.
    Bruno Desthuilliers, Apr 7, 2010
    #5
  6. Tim Arnold

    Tim Arnold Guest

    On Apr 6, 11:19 am, Jean-Michel Pichavant <>
    wrote:
    > Tim Arnold wrote:
    > > Hi,
    > > I have a few classes that manipulate documents. One is really a
    > > process that I use a class for just to bundle a bunch of functions
    > > together (and to keep my call signatures the same for each of my
    > > manipulator classes).

    >
    > > So my question is whether it's bad practice to set things up so each
    > > method operates on self.document or should I pass document around from
    > > one function to the next?
    > > pseudo code:

    >
    > > class ManipulatorA(object):
    > >     def process(self, document):
    > >         document = self.do_one_thing(document)
    > >         document = self.do_another_thing(document)
    > >         # bunch of similar lines
    > >         return document

    >
    > > or

    >
    > > class ManipulatorA(object):
    > >     def process(self, document):
    > >         self.document = document
    > >         self.do_one_thing() # operates on self.document
    > >         self.do_another_thing()
    > >         # bunch of similar lines
    > >         return self.document

    >
    > > I ask because I've been told that the first case is easier to
    > > understand. I never thought of it before, so I'd appreciate any
    > > comments.
    > > thanks,
    > > --Tim

    >
    > Usually, when using classes as namespace, functions are declared as
    > static (or as classmethod if required).
    > e.g.
    >
    > class Foo:
    >     @classmethod
    >     def process(cls, document):
    >         print 'process of'
    >         cls.foo(document)
    >
    >     @staticmethod
    >     def foo(document):
    >         print document
    >
    > In [5]: Foo.process('my document')
    > process of
    > my document
    >
    > There is no more question about self, 'cause there is no more self. You
    > don't need to create any instance of Foo neither.
    >
    > JM


    Thanks for the input. I had always wondered about static methods; I'd
    ask myself "why don't they just write a function in the first place?"

    Now I see why. My situation poses a problem that I guess static
    methods were invented to solve. And it settles the question about
    using self.document since there is no longer any self. And as Bruno
    says, it's easier to understand and refactor.

    thanks,
    --Tim
    Tim Arnold, Apr 7, 2010
    #6
  7. Tim Arnold

    Lie Ryan Guest

    On 04/07/10 18:34, Bruno Desthuilliers wrote:
    > Lie Ryan a écrit :
    > (snip)
    >
    >> Since in function in python is a first-class object, you can instead do
    >> something like:
    >>
    >> def process(document):
    >> # note: document should encapsulate its own logic
    >> document.do_one_thing()

    >
    > Obvious case of encapsulation abuse here. Should a file object
    > encapsulate all the csv parsing logic ? (and the html parsing, xml
    > parsing, image manipulation etc...) ? Should a "model" object
    > encapsulate the presentation logic ? I could go on for hours here...


    Yes, but no; you're taking it out of context. Is {csv|html|xml|image}
    parsing logic a document's logic? Is presentation a document's logic? If
    they're not, then they do not belong in document.
    Lie Ryan, Apr 8, 2010
    #7
  8. Lie Ryan a écrit :
    > On 04/07/10 18:34, Bruno Desthuilliers wrote:
    >> Lie Ryan a écrit :
    >> (snip)
    >>
    >>> Since in function in python is a first-class object, you can instead do
    >>> something like:
    >>>
    >>> def process(document):
    >>> # note: document should encapsulate its own logic
    >>> document.do_one_thing()

    >> Obvious case of encapsulation abuse here. Should a file object
    >> encapsulate all the csv parsing logic ? (and the html parsing, xml
    >> parsing, image manipulation etc...) ? Should a "model" object
    >> encapsulate the presentation logic ? I could go on for hours here...

    >
    > Yes, but no; you're taking it out of context. Is {csv|html|xml|image}
    > parsing logic a document's logic? Is presentation a document's logic? If
    > they're not, then they do not belong in document.


    Is len() a list logic ? If yes, it should belong to list !-)

    There are two points here : the first is that we (that is, at least, you
    and me) just don't know enough about the OP's project to tell whether
    something should belong to the document or not. period. The second point
    is that objects don't live in a splendid isolation, and it's perfectly
    ok to have code outside an object's method working on the object.

    wrt/ these two points, your "document should encapsulate its own logic"
    note seems a bit dogmatic (and not necessarily right) to me - hence my
    answer.
    Bruno Desthuilliers, Apr 8, 2010
    #8
  9. Tim Arnold

    Tim Arnold Guest

    On Apr 8, 4:20 am, Bruno Desthuilliers <bruno.
    > wrote:
    > Lie Ryan a écrit :
    >
    >
    >
    >
    >
    > > On 04/07/10 18:34, Bruno Desthuilliers wrote:
    > >> Lie Ryan a écrit :
    > >> (snip)

    >
    > >>> Since in function in python is a first-class object, you can instead do
    > >>> something like:

    >
    > >>> def process(document):
    > >>>     # note: document should encapsulate its own logic
    > >>>     document.do_one_thing()
    > >> Obvious case of encapsulation abuse here. Should a file object
    > >> encapsulate all the csv parsing logic ? (and the html parsing, xml
    > >> parsing, image manipulation etc...) ? Should a "model" object
    > >> encapsulate the presentation logic ? I could go on for hours here...

    >
    > > Yes, but no; you're taking it out of context. Is {csv|html|xml|image}
    > > parsing logic a document's logic? Is presentation a document's logic? If
    > > they're not, then they do not belong in document.

    >
    > Is len() a list logic ? If yes, it should belong to list !-)
    >
    > There are two points here : the first is that we (that is, at least, you
    > and me) just don't know enough about the OP's project to tell whether
    > something should belong to the document or not. period. The second point
    > is that objects don't live in a splendid isolation, and it's perfectly
    > ok to have code outside an object's method working on the object.
    >
    > wrt/ these two points, your "document should encapsulate its own logic"
    > note seems a bit dogmatic (and not necessarily right) to me - hence my
    > answer.


    The 'document' in this case is an lxml Elementtree, so I think it
    makes sense to have code outside the object (e.g. static methods)
    working on the object.
    thanks,
    --Tim
    Tim Arnold, Apr 8, 2010
    #9
  10. Tim Arnold

    Lie Ryan Guest

    On 04/08/10 18:20, Bruno Desthuilliers wrote:
    > Lie Ryan a écrit :
    >> On 04/07/10 18:34, Bruno Desthuilliers wrote:
    >>> Lie Ryan a écrit :
    >>> (snip)
    >>>
    >>>> Since in function in python is a first-class object, you can instead do
    >>>> something like:
    >>>>
    >>>> def process(document):
    >>>> # note: document should encapsulate its own logic
    >>>> document.do_one_thing()
    >>> Obvious case of encapsulation abuse here. Should a file object
    >>> encapsulate all the csv parsing logic ? (and the html parsing, xml
    >>> parsing, image manipulation etc...) ? Should a "model" object
    >>> encapsulate the presentation logic ? I could go on for hours here...

    >>
    >> Yes, but no; you're taking it out of context. Is {csv|html|xml|image}
    >> parsing logic a document's logic? Is presentation a document's logic? If
    >> they're not, then they do not belong in document.

    >
    > Is len() a list logic ? If yes, it should belong to list !-)


    Yes, that's why list.__len__() belongs to list while len() is a
    convenience function that doesn't carry any concrete implementation.

    > There are two points here : the first is that we (that is, at least, you
    > and me) just don't know enough about the OP's project to tell whether
    > something should belong to the document or not. period.


    I think I see your point here. I retract my suggestion that it is
    suitable for OP's purpose since I just realized OP is in a better
    position to make the decision.

    > The second point
    > is that objects don't live in a splendid isolation, and it's perfectly
    > ok to have code outside an object's method working on the object.
    > wrt/ these two points, your "document should encapsulate its own logic"
    > note seems a bit dogmatic (and not necessarily right) to me - hence my
    > answer.


    I agree with you about there are certain logics that should not be
    inside the object (that's why I qualify the statement with `should`).
    Glue logic, by definition, cannot be inside an object. I don't think we
    are actually in disagreement here. But I think the dogma, followed with
    caution, is generally good.
    Lie Ryan, Apr 9, 2010
    #10
  11. Tim Arnold a écrit :
    > On Apr 8, 4:20 am, Bruno Desthuilliers <bruno.

    (snip)
    >> There are two points here : the first is that we (that is, at least, you
    >> and me) just don't know enough about the OP's project to tell whether
    >> something should belong to the document or not. period. The second point
    >> is that objects don't live in a splendid isolation, and it's perfectly
    >> ok to have code outside an object's method working on the object.
    >>
    >> wrt/ these two points, your "document should encapsulate its own logic"
    >> note seems a bit dogmatic (and not necessarily right) to me - hence my
    >> answer.

    >
    > The 'document' in this case is an lxml Elementtree, so I think it
    > makes sense to have code outside the object.


    Indeed. It's the only sensible thing to do here.
    Bruno Desthuilliers, Apr 9, 2010
    #11
    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. Ralf W. Grosse-Kunstleve
    Replies:
    16
    Views:
    559
    Lonnie Princehouse
    Jul 11, 2005
  2. Ralf W. Grosse-Kunstleve
    Replies:
    18
    Views:
    578
    Bengt Richter
    Jul 11, 2005
  3. Ralf W. Grosse-Kunstleve
    Replies:
    2
    Views:
    389
    Dan Sommers
    Jul 12, 2005
  4. falcon
    Replies:
    0
    Views:
    357
    falcon
    Jul 31, 2005
  5. lallous

    to pass self or not to pass self

    lallous, Mar 15, 2010, in forum: Python
    Replies:
    19
    Views:
    381
    Gregory Ewing
    Mar 20, 2010
Loading...

Share This Page