Confusion About Classes

F

flamesrock

Hi,

I've been playing like mad with all sorts of python modules..but I
still can't seem to get my head around the proper use of a class and
self. The question stems from this code I made(snippet):
--------------------------------------------------------------------------------------
import httplib, ftplib, urllib2, exPyCrypto, score_configurations
#custom

class create_server:
def __init__(self, domain, servername, master_ftpUSER,
master_ftpPASS, score_ftpUSER, score_ftpPASS, httpport=None,
ftpport=None):
self.domain = domain
if httpport is None:
self.__httpport = '80'
else:
self.__httpport = httpport
if ftpport is None:
self.__ftpport = '21'
else:
self.__ftpport = ftpport
if servername is None:
self.__servername = 'SCORE-SERVER'
else:
self.__servername = servername
self.master_ftpUSER = master_ftpUSER
self.master_ftpPASS = master_ftpPASS
self.score_ftpUSER = score_ftpUSER
self.score_ftpPASS = score_ftpPASS
self.parser = ConfigParser.ConfigParser()

def createUniversalConfig(self, score_domain, score_servername,
score_port):
''''''
self.parser.add_section('score')
self.parser.set('score', 'domain', self.score_domain)
self.parser.set('score', 'server', self.score_servername)
self.parser.set('score', 'server', self.score_port)
-------------------------------------------------------------------------------------

The goal is to create a create_server object with the given parameters,
and then call the method createUniversalConfig() without passing and
parameters to it. So here are my questions:
1) in the function parameter heading <<def createUniversalConfig(self,
score_domain, score_servername, score_port):>> do I need to include
those parameters as written, like this-- <<def
createUniversalConfig(self, self.score_domain, self.score_servername,
self.score_port):>> or not pass any parameters at all?
2) Do I reference the body of the function like I originally wrote it:
self.parser.add_section('score')
self.parser.set('score', 'domain', self.score_domain)
self.parser.set('score', 'server', self.score_servername)
self.parser.set('score', 'server', self.score_port)
or, like this
self.parser.add_section('score')
self.parser.set('score', 'domain', score_domain)
self.parser.set('score', 'server', score_servername)
self.parser.set('score', 'server', score_port)
(if the goal is to call the method from the object without any
parameters)
3) Can I create a configParser object and just call self.parser.set()
inside the function without passing it as a parameter, or do I pass it
as a parameter and call it as parser.set (without the 'self'
statement.)

Basically..I'm confused on the proper use of 'self' in this type of
situation, even after going through all these different tutorials. Any
ideas?

-thanks in advance\
 
S

Steven Bethard

flamesrock said:
Hi,

I've been playing like mad with all sorts of python modules..but I
still can't seem to get my head around the proper use of a class and
self. The question stems from this code I made(snippet):
[snip misaligned code]

When posting to c.l.py it's greatly appreciated if you use spaces
instead of tabs in your code. Many newsreaders strip out tabs.
The goal is to create a create_server object with the given parameters,
and then call the method createUniversalConfig() without passing and
parameters to it.


Sounds like you want to write:

def createUniversalConfig(self):
''''''
self.parser.add_section('score')
self.parser.set('score', 'domain', self.score_domain)
self.parser.set('score', 'server', self.score_servername)
self.parser.set('score', 'server', self.score_port)

Then you can do something like:

cs = create_server(... appropriate arguments ...)
cs.createUniversalConfig()

However, this will only work if somewhere previously (probably
__init__), you wrote assignment statements like:

self.score_domain = ...
self.score_servername = ...
self.score_port = ...

Looking at your code, I don't see that you've done this anywhere. Where
should score_domain, score_servername and score_port be coming from?
Are they the same as the 'domain', 'servername' and 'httpport'
parameters to __init__? If so, you should write your code like:

def createUniversalConfig(self):
''''''
self.parser.add_section('score')
self.parser.set('score', 'domain', self.domain)
self.parser.set('score', 'server', self.servername)
self.parser.set('score', 'server', self.__httpport)

As an aside, there's probably no need to prefix your variables with
double-underscores -- this causes name mangling that's generally not
necessary in a "we're all consenting adults" language like Python.

Steve
 
M

M.E.Farmer

flamesrock wrote:
[snip]
3) Can I create a configParser object and just call self.parser.set()
inside the function without passing it as a parameter, or do I pass it
as a parameter and call it as parser.set (without the 'self'
statement.)

Basically..I'm confused on the proper use of 'self' in this type of
situation, even after going through all these different tutorials. Any
ideas?

-thanks in advance\
Ok you have several problems that I see.
First you are having namespace difficulties.
I am not sure you 'get it' yet , but if you stay around long enough you
will ;)
http://docs.python.org/tut/node11.html

The proper use of 'self' in a class is its namespace.
You *have* to pass 'self' to all member functions of a class sp the all
can have a reference to the namespace.
It makes it easy to pass data back and forth between functions in a
class.
Below is an example of functions calling functions within a class and
setting attributes, maybe this will clear it up some
example:
py>class bla:
.... def __init__(self):
.... self.data=0
.... def setData(self, data):
.... self.data = data
.... def getData(self):
.... return self.data
.... def nullData(self):
.... self.setData(None)

Namespace is one of those crucial concepts you *must* master in python.
Do a search on google for python namespace, and read, and code, till
you get it. Master namespace if you have not already. Break out an
interpreter and hack away. Use dir() around your classes and functions
and 'see' for yourself what is in them. Do a search on this newsgroup
for namespace. This has been explained much better than I can.

Second if you haven't done it yet read up on configparser.
http://docs.python.org/lib/module-ConfigParser.html
before implementing a universalconfigwriter/reader you need to know how
to find previously written sections and options , and add error
checking etc..
Especially note this page.
(Hint this will save you from many long boring hours reinventing all
this junk and avoiding some eval hack to get the stuff back to the
right type.)
If you think I am kidding note others in this newsgroup have been there
done that, not me of course, I never need documentation ;)
Hth,
M.E.Farmer
 
F

flamesrock

Thanks for the responses! And sorry for the late reply, I had to force
myself away from the computer for a day.

M.E.Farmer,
Yes I've been having a little bit of trouble with name spaces, but this
self thing is actually starting to make sense the more I think about it
-- I hadn't thought too much about multiple instances of the same class
for this particular program. The notion of storing data that way makes
better sense with that example. Coming from a background in the more
'procedural' languages it was harder to grasp but I think I'm beginning
to naturally absorb the concept by working my head around these
examples

And thanks for the links :) I know this is going to be full of bugs,
but it would be nice to avoid the more serious ones.

Steven Bethard,
First, thanks for fixing up my class. I really appreciate it.
Where should score_domain, score_servername and score_port be coming from?
Are they the same as the 'domain', 'servername' and 'httpport'
parameters to __init__?
whoops..heh.. my mistake.
My original-confused- idea was to use different variable names because
I didn't want the function to interfere with the classes variables
directly as I'd be passing the objects variables to itself..if that
makes any sense. Your way makes me wonder how the heck I came to my
logifc in the first place
As an aside, there's probably no need to prefix your variables with
double-underscores -- this causes name mangling that's generally not
necessary in a "we're all consenting adults" language like Python.
Ahh..from an example on the net, I though it was a necessary thing for
the interpreter..heh. Well not having to certainly simplifies things
-thanks
 
M

M.E.Farmer

Thanks for the followup,
I just wanted to mention that you still need to read that stuff thru
several times, because...
there are no variables in python (yea I know others will say otherwise
;)
Yep, I said it, none.
There are NAMES, thats why there are NAMESPACES.
A name is just a reference or 'handle' to an object, because.....
everything in python is an OBJECT,(except for names, they are just
names).
And before you go and wipe out all those double underscores note that
python uses double underscores as special methods and other internal
details( read the docs).
A quick example is :( yeah it's deja vu)
py>class bla:
.... def __init__(self):
.... self.data=0
.... def setData(self, data):
.... self.data = data
.... def getData(self):
.... return self.data
.... def nullData(self):
.... self.setData(None)
Not all underscores method names are unnecessary.
__init__ is a special method that is called by python when we create an
instance of this class. Most of the double underscore methods are
special methods and are part of python( later you will see they can be
used for object customization )
Now back to self... self is reference to.. well self. Python is
explicit . A class has it's own namespace so we pass a referance around
to all it's member functions. when we set an attribute of a class it
can be done inside or out . Self.data is an example of setting a
attribute of an object from inside the class ( notice we referance
ourselves inside the class , because we are assigning the name to that
namespace.)
An example of settng attrbutes outside a class:
bl = bla()
bl.MyNewData = [1,2,3,4,5]
dir(bl)

As a matter of fact a common use of a class is like a container to
store data.
class null:
pass
a =null()
a.name = 'mike'
a.weight= 220
dir(a)
del a.name
Sorry if it is incoherent, I am way past bed time .
M.E.Farmer
 
S

Steven Bethard

M.E.Farmer said:
there are no variables in python

While it's true that in Python it's more appropriate to talk about names
and bindings instead of variables and values, there is a parallel, and
you can get a fair distance without having to fully convert to the
names/bindings terminology.

That being said, understanding this part of Python can aid enormously in
working with the language. If you'd like to think of it in C terms,
basically every 'name' in Python is a pointer to a PyObject, and 'names'
(as pointers) are always passed by value -- that is, you get a copy of
the pointer, but not a copy of the object.
And before you go and wipe out all those double underscores note that
python uses double underscores as special methods and other internal
details( read the docs).

Just to clarify, I was only talking about removing leading underscores
for instance variables, e.g. changing:

self.__xyz

to

self.xyz

As M.E.Farmer mentioned, you can't remove underscores on special method
names like __init__. However, when you're declaring an instance
variable, e.g.:

self.__xyz = True

then you're choosing the name here, so you can name it whatever you
want. The only reason to use leading double-underscores is if you want
Python to name-mangle the variable so it's not (easily) accessible from
subclasses. In most cases, this is unnecessary.

Steve
 
S

Steve Holden

Steven said:
M.E.Farmer said:
there are no variables in python
[...]
As M.E.Farmer mentioned, you can't remove underscores on special method
names like __init__. However, when you're declaring an instance
variable, e.g.:

self.__xyz = True

then you're choosing the name here, so you can name it whatever you
want. The only reason to use leading double-underscores is if you want
Python to name-mangle the variable so it's not (easily) accessible from
subclasses. In most cases, this is unnecessary.
While it's unnecessary in most cases, I'd like to point out that the
mechanism is mostly to avoid inadvertent clashes in the object namespace.

So, if you are designing a class explicitly to be subclassed, that's
when the use of mangled names can pay off.

Of course, if the subclass implementor actually *does* need access to
your instance variables they will curse you if you've mangled them.

unwrapping-that-mangling-isn't-pretti-ly y'rs - steve
 
F

flamesrock

Well, I took a short excursion into xml for a different part of the
program, but the class is now finished!! (source below) I have a few
more questions for you guys.

1)If I set
self.serverConfig = file(os.path.join('configuration','score.conf'),
'w')
and then go self.serverConfig.close(), is there a way to open it in
read mode without calling the filename directly? Like
self.serverConfig.open('r') -which doesn't work BTW- instead of
open(os.path.join('configuration','score.conf'), 'r')? Using
open(self.ServerConfig, 'r') doesn't seem to work either.

2) A problem arose when converting the encoded file back into a string
for decoding; the \n's seemed to have dissapeared so it returned an
error when I tried to decode. Is there a way to stop python from
disposing of those those characters before writing to file?

3) Is there way to retrieve the timestamp of a file via ftp?

Ahhhhh...now *that* makes sense. So dynamically typed variables aren't
variables at all...but just another term for pointers? cool, I like
that. And thanks for the examples, guys. Its coming together and I'm
starting to actually 'get it' :)

So name mangling basically follows the rules of private and public in
Java? (I have limited experience in java so don't quote me on that.)

(Google groups isn't displaying the spaces correctly, so I added four
*'s = 1 four space indentation..)
import ftplib, ezPyCrypto, ConfigParser
import traceback, sys, os
#-------------------------------------------------------------------------------
class create_server:
****'''Create a create_server object whenever a new server is to be
added to
****the SCORE network.'''
****def __init__(self, absCFGpath, domain, servername, master_ftpUSER,
****master_ftpPASS, score_ftpUSER='anonymous',
score_ftpPASS='anonymous',
****scorecontact='(e-mail address removed)', maxusers='unlimited',
httpport='80',
****ftpport='21', passivemode=True):
********self.domain = domain
********self.httpport = httpport
********self.ftpport = ftpport
********self.servername = servername
********self.maxusers = maxusers
********self.scorecontact = scorecontact
********try:
************self.serverConfig =
file(os.path.join('configuration','score.conf'), 'w')
********except:
************os.mkdir('configuration')
************self.serverConfig =
file(os.path.join('configuration','score.conf'), 'w')
********self.absCFGpath = absCFGpath
********self.master_ftpUSER = master_ftpUSER
********self.master_ftpPASS = master_ftpPASS
********self.score_ftpUSER = score_ftpUSER
********self.score_ftpPASS = score_ftpPASS
********self.passivemode = passivemode
********self.parser = ConfigParser.ConfigParser()

#-------------------------------------------------------------------------------
****def createUniversalConfig(self):
********'''Creates the SCORE servers main configuration file.'''
********self.parser.add_section('score')
********self.parser.set('score', 'domain', self.domain)
********self.parser.set('score', 'servername', self.servername)
********self.parser.set('score', 'httpport', self.httpport)
********self.parser.set('score', 'ftpport', self.ftpport)
********self.parser.set('score', 'maxusers', self.maxusers)
********self.parser.set('score', 'scorecontact', self.scorecontact)
********self.parser.write(self.serverConfig)
********self.serverConfig.close()
********return open(os.path.join('configuration','score.conf'), 'r')
#-------------------------------------------------------------------------------
****def editUniversalConfig(self, section, key, value):
********'''edit the SCORE servers main configuration file.'''
********self.serverConfig =
open(os.path.join('configuration','score.conf'), 'w')
********self.parser.set(section, key, value)
********self.serverConfig.close
#-------------------------------------------------------------------------------
****def createUSERfile(self):
********'''Creates an encrypted ascii public ftp password file that
clients use
********to decode after logging in'''
********crypt = ezPyCrypto.key()
********userFile = file(os.path.join('configuration','uFile.enc'), 'w')
********userFile.write(crypt.encStringToAscii(self.score_ftpUSER))
********userFile.close()
********userFile = open(os.path.join('configuration','uFile.enc'), 'r')
********return userFile
#-------------------------------------------------------------------------------
****def createPASSfile(self):
********'''Creates an encrypted ascii public ftp password file that
clients use
********to decode after logging in'''
********crypt = ezPyCrypto.key()
********passFile = file(os.path.join('configuration','pFile.enc'), 'w')
********passFile.write(crypt.encStringToAscii(self.score_ftpPASS))
********passFile.close()
********passFile = open(os.path.join('configuration','pFile.enc'), 'r')
********return passFile
#-------------------------------------------------------------------------------
****def uploadConfigs(self):
********'''Uploads the universal config/ftpuser/pass files to the
correct directories on the site'''
********##print "Files:", sys.argv[1:] relic..

********print "Logging in..."
********ftp = ftplib.FTP()
********ftp.set_pasv(self.passivemode) #true if passive, false if
active
********ftp.connect(self.domain, self.ftpport)
********print ftp.getwelcome()
********try:
************try:
****************ftp.login(self.master_ftpUSER, self.master_ftpPASS)
****************ftp.cwd(self.absCFGpath) #*the SCORE root directory
****************print "Currently in:", ftp.pwd()
****************print "Uploading..."
****************sConfig = self.createUniversalConfig()
****************uFile = self.createUSERfile()
****************pFile = self.createPASSfile()
****************ftp.storlines('STOR score.conf', sConfig)
****************try:
********************ftp.cwd(self.absCFGpath + '/files')
****************except ftplib.error_perm: #*if dir doesn't exist
********************ftp.mkd('files')
********************ftp.cwd(self.absCFGpath + '/files') #change to
config directory
****************ftp.storlines('STOR uFile.enc', uFile)
****************ftp.storlines('STOR pFile.enc', pFile)
****************sConfig.close()
****************uFile.close()
****************pFile.close()
****************print "OK"

****************print "Files:"
****************print ftp.retrlines('LIST')
************finally:
****************print "Quitting..."
************ftp.quit()
********except:
************traceback.print_exc()
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
-thanks,
flamesrock
 

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,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top