Question about Object Oriented + functions/global vars?

F

flamesrock

ok, so to my knowledge, object oriented means splitting something into
the simplest number of parts and going from there. 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
# ftp_pool = FTP_pool(file_id,1,40,global_uid,global_pwd)
# 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:
# 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"
# 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):
# 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)


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?

-thanks in advance
 
C

Christopher J. Bottaro

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

That sounds like normal top down imperative (procedural) programming to me.
But the question is- when is it enough?

Thats a judgment call on the programmer's part.
For example I have the following code: [...snip...]

would the lines with '>#' best be split up into a seperate function,
for example:
#def upload(ftp, file): [...snip...]
and then doing the call 'upload(file_id)', or is it a better practice
to leave things the way they were? I'm confused.

Judgment call...=)
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?

1. The upload function is not an object.
2. Functions are made to be called.
3. Some people think globals should be avoided if possible. I think it
depends on the size of your project and how much convenience they can give
you vs. how much confusion they can potentially cause.
-thanks in advance

Btw, object oriented programming is the splitting up of the program into
things called object which are data and their related methods. Bah, its
hard to explain, but its like instead of focusing on functions that
manipulate a square, you instead have a square and its related methods.
Also, I can't think of OOP without thinking of polymorphism. Ehh, this
stuff is too hard for me to explain, it would be easier with examples (but
too long for me to write)...=)

-- C
 
W

wittempj

Well, if you want to apply object orientatation techniques to your work
you would get something like this. Polymorphism is used to distinct
between the ftp method. Another concept is data encapsulation, see the
filedescription class . A third technique is inheritance - ftp is
derived from an existing object, the get classes are derived from my
ftp class.

But most of all it is a different way of organizing your work, for your
code I think it makes sense to split the work between an ftp class and
a filedescrition class - where you can add methods to record the status
of the retrieval.

#!/usr/bin/env python
import ftplib
import os.path
import sys

class ftp_err(Exception):
pass

class ftp(ftplib.FTP):
def __init__(self, address, filedescription, user = None, password
= None):
ftplib.FTP.__init__(self, address)
self.login(user, password)
self.filedescription = filedescription

def list(self):
return self.nlst()

def cd(self, directory):
self.cwd(directory)

def quit(self):
self.quit()

class ftp_get(ftp):
def get(self):
cmd = 'RETR %s' % self.filedescription.name
self.retrlines(cmd, open(self.filedescription.name, 'w').write)

class ftp_get_binary(ftp):
def get(self):
cmd = 'RETR %s' % self.filedescription.name
self.retrbinary(cmd, open(self.filedescription.name,
'wb').write)

class filedescription(object):
def set_name(self, name):
self.__name = name
def get_name(self):
return self.__name
name = property(get_name, set_name)

def _get_texttype(self):
ext = os.path.splitext(self.name)[1]
if ext in ('.txt', '.htm', '.html'):
return True
else:
return False

def get_texttype(self):
return self._get_texttype()
text = property(get_texttype)

def get_binarytype(self):
return not self._get_texttype()
binary = property(get_binarytype)

f1 = filedescription()
f1.name = 'download.ht'
f2 = filedescription()
f2.name = 'download.html'

ftp_site = 'ftp.python.org'
ftp_dir = 'pub/docs.python.org'

for i in (f1, f2):
try:
f = None
if i.text:
f = ftp_get(ftp_site, i)
elif i.binary:
f = ftp_get_binary(ftp_site, i)
f.cd(ftp_dir)
f.get()
except Exception, e:
print >> sys.stderr, '%s: %s' % (e.__class__.__name__, e)
 
G

gene tani

#include canonical design pattern advice

longjmp(Borders or other_big_chain_bookstore)

opt1=fopen("Oreilly's Head first design pattern","r")
opt2=fopen("design patterns book by Shalloway and trott (i think that's
their names)","r")

another=poll("any other intro to DP books that people like?")
 
B

bruno modulix

Christopher J. Bottaro wrote:
(snip)
1. The upload function is not an object.

Yes it is. In Python, everything's an object.
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'instancemethod' object has no attribute 'foobar'
 
B

bruno modulix

gene said:
#include canonical design pattern advice

longjmp(Borders or other_big_chain_bookstore)

opt1=fopen("Oreilly's Head first design pattern","r")
opt2=fopen("design patterns book by Shalloway and trott (i think that's
their names)","r")

another=poll("any other intro to DP books that people like?")

another.append(what_about("GOF"))
 
B

bruno modulix

flamesrock said:
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.
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 :
'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...)
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top