Question about Object Oriented + functions/global vars?

bruno modulix onurb at xiludom.gro
Tue Jun 7 05:17:35 EDT 2005


flamesrock wrote:
> ok, so to my knowledge, object oriented means splitting something into
> the simplest number of parts and going from there.

So you may want to refine your knowledge. What you're talking about is
top-down functional decomposition, and it's almost the opposite of OO.

<overly-simplified>
OO is about interacting objects. An object is defined by an identity, a
state, a behaviour, and (even if implicitely) an interface. Objects do
interact by sending messages to each others. The interface of a given
object is the list of *what* messages this object understands (ie: can
respond to). The behavior is defined by *how* a given object responds to
messages (different objects can respond differently to the same message,
and a given object may respond differently to the same message according
to it's current state). The state is made up of the object's internals
vars.
</overly-simplified>

> But the question is-
> when is it enough?
> 
> For example I have the following code:
> 
> #def put_file(file_id, delete=False):
> #    """  Function to put the file on the FTP Server
> #    """
> #    print "["+file_id+"] FTP for this file started"
> #    print "[" + file_id + "] Connecting to machine " + global_addr

Where does this 'global_addr' var come from ?

> #    ftp_pool = FTP_pool(file_id,1,40,global_uid,global_pwd)

idem for global_uid and global_pwd. And what are those magic numbers 1
and 40 ?

> #    print 'in put_file'
> #    try:
> #        ftp = ftplib.FTP(global_addr)
> #        ftp.login(global_uid, global_pwd)
> #        print ftp.getwelcome() +'\n'
> #        ftp.cwd(global_ftp_loc)
> 
>>#        ext = os.path.splitext(file_id)[1]
>>#        if ext not in (".sc4", ".snpickle"):
>>#            ftp.storlines("STOR " + file_id, open(file_id))
>>#        else:
>>#            ftp.storbinary("STOR " + file_id, open(file_id, "rb"), 1024)
> 
> #        ftp.quit()
> #        ftp_pool.close_all()
> #    except:

Take care of too-large-except-clause. Here it's ok since you re-raise
the exception, but this is usually a bad practice to not specify the
exception class(es) you want to catch. Hint: sys.exit() works by raising
 SystemExit.

> #        ftp_pool.close_all()
> #        print "[" + file_id + "]Unable to access FTP location"
> #        print "[" + file_id + "]Error:" + str(sys.exc_info()[0]) + " "
> + str(sys.exc_info()[1])
> #        upload_status[file_id] = "FAILED"

Where does this upload_status comes from ?

> #        raise
> #    else:
> #        print "[" + file_id + "] FTP for file completed"
> #        upload_status[file_id] = "SUCCESS"

> 
> would the lines with '>#' best be split up into a seperate function,
> for example:
> 
> #def upload(ftp, file):

dont use 'file', it shadows the builtin file class.

> #    ext = os.path.splitext(file)[1]
> #    if ext in (".txt", ".htm", ".html"):
> #        ftp.storlines("STOR " + file, open(file))
> #    else:
> #        ftp.storbinary("STOR " + file, open(file, "rb"), 1024)


Nope.

<IMHO> The calling code should not have to worry about this. This should
be a responsability of some object(s) abstracting the file, and should
be implemented as different behaviors (using text or binary) in response
to the same message.</IMHO> In short, this could look like:

the_file = FtpFileDescriptor(path)
try:
  # the_file objects knows if it must use text or binary.
  # we, as client, just don't care about this gory detail.
  the_file.store()
except MyFtpUploadError, e:
  # TODO
  pass

> 
> and then doing the call 'upload(file_id)', or is it a better practice
> to leave things the way they were? I'm confused.
> 
> Finally, is it considered 'un-object-oriented' in python to have
> functions inside a module that are called by objects (ie the upload
> function above) and/or use global variables in combination?

<disgression>
In Python, everything's an object (well... almost everything). At
runtime, a module is an object :

>>> ftplib
<module 'ftplib' from '/usr/lib/python2.3/ftplib.pyc'>
>>> ftplib.__class__
<type 'module'>
>>> ftplib.__class__.__name__
'module'

module-level 'functions' are methods of the given module object, and
'global' vars (the term 'global' is somewhat misleading, since it reaaly
means 'module-level') are attributes of the module object.
</disgression>

Now what makes the difference between OO and non-OO is not the use of
classes, objects etc, but how you *design* your program. Your code
snippet makes use of OO features (classes, objects etc), but is typical
of procedural style. Not because you use 'module-level' functions and
vars, but because there's no abstraction, no separation of concerns and
responsabilities.


> -thanks in advance

HTH (not sure, but...)

-- 
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"



More information about the Python-list mailing list