Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
Flea110
Apr 3, 2006
I've spent the last week or so writing a battle simulator for the board game Axis & Allies. I'm fairly new to programming, and it's my first program that uses classes.

I'd appreciate any constructive criticism, or any other advice or opinions.

http://pastebin.com/f741d6759

Adbot
ADBOT LOVES YOU

Scaevolus
Apr 16, 2007

Flea110 posted:

I've spent the last week or so writing a battle simulator for the board game Axis & Allies. I'm fairly new to programming, and it's my first program that uses classes.

I'd appreciate any constructive criticism, or any other advice or opinions.

http://pastebin.com/f741d6759

Line 112, you want to use the "copy" module.

You should be using dicts instead of tuples and lists. That would make line 137 read something like units['battleship']['count'] *= 2. But really, you should be doing proper OOP-- this sort of thing is the textbook example of it.

Don't use range, it creates an entire list. Use xrange, it creates an iterator.

The main problem is that your code reads like C, not like Python :)

checkeredshawn
Jul 16, 2007

I work for the Systems group at my school and I'm supposed to write an Account Request Form where students sign up for a UNIX account so they can access our servers and use our lab computers. Originally the sign up process was done as follows:

1. Run an account program on one of our lab machines with requested username, and other bits of information like first and last name.
2. Fill out and sign a paper form with all sorts of information like your name, school ID number, phone number, which type of account you're requesting (are you a CS undergraduate, graduate student, just taking a CS course but not a major?), etc.

I'm supposed to move that second form online, and I was originally doing it in Perl using CGI.pm. My friend then told me that I should be using templates and that the HTML should be separate from the logic, so I tried to go and learn how to use HTML::Template. Now I'm realizing that this code is probably going to be a big unreadable mess as I do not have much experience in CGI or Perl.

I'd appreciate some opinions on how you guys think this should be done. Is there an HTML template module for Python? Should I be doing this with CGI?

hey mom its 420
May 12, 2007

Yeah there is.
It seems like the best solution here would be Django. It's a web framework for Python. It features a very good templating engine, database abstraction and is generally very easy to use. I'd go so far as to say it's one of the most well planned out and best programming tools today. There's a Django thread here in CoC, so I'd suggest starting there.

deimos
Nov 30, 2006

Forget it man this bat is whack, it's got poobrain!
If it's a simple enough page, web.py with mako is also suitable and simple.

DTMTCM
Feb 18, 2005
I misclicked post icon so I have this account now.
I may be an idiot (most likely scenario) but it seems that the csv module prints "\r\r\n" for new lines in Windows and I don't see anyway to change this functionality.

Edit: Further research shows I'm an idiot. I wasn't opening the file with "wb".

DTMTCM fucked around with this message at 20:55 on Jun 30, 2008

Scaevolus
Apr 16, 2007

checkeredshawn posted:

I'd appreciate some opinions on how you guys think this should be done. Is there an HTML template module for Python? Should I be doing this with CGI?

Django is overkill for this. Web.py is nice and simple (read the tutorial), although it doesn't have the most extensive documentation. Web.py has a templating system, allowing you to write stuff like this:
templates/index.html:
code:
$def with (name)
<html>
<body>
$if name:
    I just wanted to say <em>hello</em> to $name.
$else:
    <em>Hello</em>, world!
</body>
</html>
and then in your python script, you would just do
code:
render = web.template.render('templates/')
print render.index("Bob")
Cheetah is another templating system which is faster and has more features and much better documentation. You'll want to use it if you find web.py's templating too restrictive.

If you have any difficulties, talk to us on #cobol at irc.synirc.net.

ATLbeer
Sep 26, 2004
Über nerd
Here's an oddity I can't seem to figure out. I have a list of objects that I can interate through but, how to I operate on them?

This is a very simplistic example but, demonstrates what I want
code:
k = [1,2,3,4,5,6,7]
for i in k:
 i = 0
How do I set all the elements in k to 0 by interating through the objects?

Caveat: without the obvious iterating via Index. I want to maintain using it by objects? Is that possible or do I have to use indices?

Not*
for x in range(len(k)):
k[x] = 0

ATLbeer fucked around with this message at 00:24 on Jul 1, 2008

hey mom its 420
May 12, 2007

You can try
code:
for i, e in enumerate(k):
  k[i] = 0
But a more elegant solution would be to just map 0 to the list
code:
[0 for e in k]
Of course this copies a list and doesn't modify it in place. But if you're worried about copying large datasets, you shouldn't be using lists in the first place but generators and then map stuff to generators using generator expressions or functions from the itertools module.

Allie
Jan 17, 2004

code:
>>> k = range(1, 8)
>>> k
[1, 2, 3, 4, 5, 6, 7]
>>> for i, n in enumerate(k):
...     k[i] = 0
... 
>>> k
[0, 0, 0, 0, 0, 0, 0]
When you assign to i it just changes the variable to point to a different object. You have to assign to the list directly, and enumerate() will conveniently give you a counter to do that.

hey mom its 420
May 12, 2007

:cool:

ATLbeer
Sep 26, 2004
Über nerd
Well.. I guess I should have used my complete example. Simplifying it kind of changes the complexity.

This is my current function.

code:
def clense_table(table):
	for x in range(len(table)):
		try:
			for y in range(len(table[x])):
				table[x][y] = clense_cell(table[x][y])
		except:
			pass
	return table
(*Fixed a bug of omission... len(x) should have been len(table[x]) .. see... too complex :v:)
It's a multi-dimensional table of unknown dimensions and each cell needs to be slightly massaged to eliminate some unneeded cruft

I would rather
code:
def clense_table(table):
 for row in table:
  for cell in row:
   cell = clense_cell(cell)
That's obviously a lot more elegant and easier to read.

ATLbeer fucked around with this message at 00:33 on Jul 1, 2008

hey mom its 420
May 12, 2007

Watch out .... in your first example, you're modifying the arguments in place and then returning a copy. So if someone passes a list to that function and tries to use the same list later on, they'll find it's been mysteriously changed.
Why not just do
code:
def cleanse_table(table):
  return [[cleanse_cell(cell) for cell in row] for row in table]
Also, you're spelling cleanse wrong :science:
Also, it's generally not cool to just use catch-all except clauses because then they also catch KeyboardInterrupt exceptions and whatnot.

hey mom its 420 fucked around with this message at 00:35 on Jul 1, 2008

ATLbeer
Sep 26, 2004
Über nerd

Bonus posted:

Watch out .... in your first example, you're modifying the arguments in place and then returning a copy. So if someone passes a list to that function and tries to use the same list later on, they'll find it's been mysteriously changed.
Why not just do
code:
def cleanse_table(table):
  return [[cleanse_cell(cell) for cell in row] for row in table]

Can I get the Python man pages that explain that syntax :downs:

hey mom its 420
May 12, 2007

Sure, it's section 5.1.4 here http://docs.python.org/tut/node7.html

It's quite simple actually, this is how list comprehensions behave:
code:
>>> foo = [1,2,3,4,5]
>>> [x*2 for x in foo]
[2, 4, 6, 8, 10]
>>> [x/2 for x in foo if x % 2 == 0]
[1, 2]
>>> strings = ['hehe', 'woot', what']
>>> [st.upper() for st in strings]
['HEHE', 'WOOT', 'WHAT']

ATLbeer
Sep 26, 2004
Über nerd

Bonus posted:

Sure, it's section 5.1.4 here http://docs.python.org/tut/node7.html

It's quite simple actually, this is how list comprehensions behave:
code:
>>> foo = [1,2,3,4,5]
>>> [x*2 for x in foo]
[2, 4, 6, 8, 10]
>>> [x/2 for x in foo if x % 2 == 0]
[1, 2]
>>> strings = ['hehe', 'woot', what']
>>> [st.upper() for st in strings]
['HEHE', 'WOOT', 'WHAT']
That is one of those reasons why Python is so much fun to work with. When I was learning Python I was insanely happy to discover list.sort(func). So elegant

Are there enough of these for a Python tips and tricks thread?

Allie
Jan 17, 2004

I think Python's standard library surprises me the most when it comes to discovering new things. PyMOTW is great for learning about parts of the library you've never even noticed.

I also like using my browser's search on the standard library's index. Just search for whatever you're dealing with, you'll probably find something relevant.

deedee megadoodoo
Sep 28, 2000
Two roads diverged in a wood, and I, I took the one to Flavortown, and that has made all the difference.


Recommending Django for writing simple cgi scripts is a bit overkill don't you think? I've used a variety of methods for writing web applications and I like mod_python the most. web.py and other cgi modules feel clunky to me. I guess it's personal preference, but mod_python makes writing cgi in python feel more like python.

king_kilr
May 25, 2007
I just set up mod_wsgi and I like it a lot, it's super easy to get going and I imagine it would be pretty easy to invoke scripts using subpress.Popen and pipe their stdout back to the user.

Bozart
Oct 28, 2006

Give me the finger.

Bonus posted:

def cleanse_table(table):
return [[cleanse_cell(cell) for cell in row] for row in table]
[/code]

when using multidimensional lists, is there a way to simply iterate over all elements regardless of depth? Maybe this is a little too matlab-y, but in m code you can do

code:
Mat = rand(100,100,100); %100x100x100 uniform random numbers
MatVec = Mat( : ); %turns 100x100x100 cube into a 1,000,000 long vector
MatVec = cumsum(MatVec); %create cummulative sum
Mat( : ) = MatVec; % put each cummulative random number in the corresponding slot
the nice thing is that it isn't dependant on the number of dimensions in the input matrix. Is there some way to define data in a grided format, and then iterate over each element (probably in a different object than a list) ?


edit: put spaces around the ":" index to remove emoticons

hey mom its 420
May 12, 2007

I don't think there's a really idiomatic way of doing that. But you can do it recursively in this manner.
- For every element in the list, check if it's a list.
--- If it is a list, call the function recursively on it.
--- If it's not a list, apply whatever transformations you want to it.

Allie
Jan 17, 2004

HatfulOfHollow posted:

Recommending Django for writing simple cgi scripts is a bit overkill don't you think? I've used a variety of methods for writing web applications and I like mod_python the most. web.py and other cgi modules feel clunky to me. I guess it's personal preference, but mod_python makes writing cgi in python feel more like python.

I would personally never ever ever use mod_python if I could avoid it. Its poorly documented code caching (which can be inconsistent across the processes it loads) is probably the most frustrating thing I've ever had to deal with when testing code. And to make matters worse you can't really test applications developed for mod_python outside of mod_python. It's a loving framework too.

I absolutely love mod_wsgi, and for quick one-off development I just write WSGI apps directly and use wsgiref.simple_server. :)

deedee megadoodoo
Sep 28, 2000
Two roads diverged in a wood, and I, I took the one to Flavortown, and that has made all the difference.


Milde posted:

I would personally never ever ever use mod_python if I could avoid it. Its poorly documented code caching (which can be inconsistent across the processes it loads) is probably the most frustrating thing I've ever had to deal with when testing code. And to make matters worse you can't really test applications developed for mod_python outside of mod_python. It's a loving framework too.

I absolutely love mod_wsgi, and for quick one-off development I just write WSGI apps directly and use wsgiref.simple_server. :)

I've run into the caching problem a few times, but it's really only been an issue if I'm developing on a live environment and constantly changing the code. Usually I develop on another box, deploy the app and hup apache.

As for not being able to test applications outside of mod_python, you can't really test PHP apps outside of mod_php either or JSP's outside of a java application server so I don't really understand where you're going with that one.

hey mom its 420
May 12, 2007

That doesn't say anything positive about mod_python, only something negative about JSP and PHP. If you develop for WSGI, you can deploy your application on any WSGI-compilant server. There's also a WSGI wrapper for mod_python that makes it possible to run WSGI apps on mod_python.

Hanpan
Dec 5, 2004

I have a really retarded question for you guys...

What advantage does coding a web application in Python offer over using a more widely used language such as PHP? I mean aside from the obvious shared hosting issues with Python, does it offer a faster page load times or is literally just the nicer syntax?

tripwire
Nov 19, 2004

        ghost flow

Hanpan posted:

I have a really retarded question for you guys...

What advantage does coding a web application in Python offer over using a more widely used language such as PHP? I mean aside from the obvious shared hosting issues with Python, does it offer a faster page load times or is literally just the nicer syntax?

In terms of development time, I couldnt really say. I do know that php is notoriously hard to make secure, and python tends to be more maintainable in the long term because the language promotes legibility and easy to understand/debug/refactor code, whereas in php you have to kind of fight against the language if you want to accomplish these things. In terms of speed, python isn't particularly fast in comparison to most other compiled languages. I think in comparison to php you will likely see slightly less throughput for many common web applications, but then again maybe python will be faster on other tasks as well. Python also has the ability to include C code through the swig, psyco, or pyrex modules, which can yield significant boosts in speed if that is a big issue for you.

tripwire fucked around with this message at 12:29 on Jul 2, 2008

Hanpan
Dec 5, 2004

tripwire posted:

In terms of development time, I couldnt really say. I do know that php is notoriously hard to make secure, and python tends to be more maintainable in the long term because the language promotes legibility and easy to understand/debug/refactor code, whereas in php you have to kind of fight against the language if you want to accomplish these things.


Ahh, thanks. I was worried because I thought there was some kind of huge performance issues between the two.

tef
May 30, 2004

-> some l-system crap ->
I'm looking for a nice imaging/drawing api/toolkit for python.

The problem is that I need to produce real time (well, frequently updates) visualisations (mostly charts) on linux/python (although preferably cross platform)

I've been looking at using a number of chart APIs but have avoided them as they produce ugly as sin.

NodeBox is Pretty but it's OSX only. Processing is also pretty but in Java. I could use.

I could also use something like pyglet or even pyqt, and I'm looking into the possibility of pycairo.

Any suggestions ?

bitprophet
Jul 22, 2004
Taco Defender
Cairo is often a good choice there. I haven't used a lot of such tools but it was not that difficult to use when I tried and it's cross platform and flexible in terms of what you can draw with it.

deimos
Nov 30, 2006

Forget it man this bat is whack, it's got poobrain!
Another one for the OP: Painless Python for Competent developers 1 of 2 and 2 of 2

ATLbeer
Sep 26, 2004
Über nerd
What the hell is going on here
code:

class MenuItem:
	def __init__(self, Text = "", URL="", Current=False):
		self.Text = ""
		self.URL = ""
		self.Current = False
class PageMenu:
	def __init__(self, Enabled=False, Items=[]):
		self.Enabled = False
		self.Items = []
class MenuContainer:
	sidemenu	= PageMenu()
	midmenu		= PageMenu()
	topmenu		= PageMenu()
	footer		= PageMenu()
	def __init__(self, Settings = None):
		self.midmenu.Items.append(MenuItem(Text="Home", URL="/"))
		self.midmenu.Items.append(MenuItem(Text="Builder", URL="/builder/"))
		self.midmenu.Items.append(MenuItem(Text="Prices", URL="/prices/"))
		self.midmenu.Enabled = True
		
for x in range(1, 5):
	m = MenuContainer()
	print len(m.midmenu.Items)
Output:
3
6
9
12

So why is this happening? I thought every time I call m=MenuContainer() it creates a new MenuContainer object and assigns it to m? Why is it the same object over and over again?

deimos
Nov 30, 2006

Forget it man this bat is whack, it's got poobrain!

ATLbeer posted:

What the hell is going on here
code:

class MenuItem:
	def __init__(self, Text = "", URL="", Current=False):
		self.Text = ""
		self.URL = ""
		self.Current = False
class PageMenu:
	def __init__(self, Enabled=False, Items=[]):
		self.Enabled = False
		self.Items = []
class MenuContainer:
	sidemenu	= PageMenu()
	midmenu		= PageMenu()
	topmenu		= PageMenu()
	footer		= PageMenu()
	def __init__(self, Settings = None):
		self.midmenu.Items.append(MenuItem(Text="Home", URL="/"))
		self.midmenu.Items.append(MenuItem(Text="Builder", URL="/builder/"))
		self.midmenu.Items.append(MenuItem(Text="Prices", URL="/prices/"))
		self.midmenu.Enabled = True
		
for x in range(1, 5):
	m = MenuContainer()
	print len(m.midmenu.Items)
Output:
3
6
9
12

So why is this happening? I thought every time I call m=MenuContainer() it creates a new MenuContainer object and assigns it to m? Why is it the same object over and over again?

def __init__(self, Enabled=False, Items=[]):

That line, change it to Items=None then
code:
if not Items:
    Items=[]
You have to remember that def is a keyword that creates a function object.


edit: wow I totally overlooked the actual problem, I should stop posting here when sleepy.

deimos fucked around with this message at 05:16 on Jul 4, 2008

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

tef posted:

Processing is also pretty but in Java. I could use.

You could try using this with Jython.

ATLbeer
Sep 26, 2004
Über nerd

deimos posted:

def __init__(self, Enabled=False, Items=[]):

That line, change it to Items=None then
code:
if not Items:
    Items=[]
You have to remember that def is a keyword that creates a function object.

Didn't make a difference

Allie
Jan 17, 2004

ATLbeer posted:

Didn't make a difference

You're using the class level variable midmenu. When you access an attribute on an instance and Python doesn't find the attribute on the instance, it looks for it in its class too before it raises AttributeError. What you need to do is instantiate all of those variables inside __init__ - they don't belong inside the class.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

ATLbeer posted:

What the hell is going on here
code:

class MenuContainer:
	sidemenu	= PageMenu()
	midmenu		= PageMenu()
	topmenu		= PageMenu()
	footer		= PageMenu()
	def __init__(self, Settings = None):
		self.midmenu.Items.append(MenuItem(Text="Home", URL="/"))
		self.midmenu.Items.append(MenuItem(Text="Builder", URL="/builder/"))
		self.midmenu.Items.append(MenuItem(Text="Prices", URL="/prices/"))
		self.midmenu.Enabled = True

This creates sidemenu, midmenu, topmenu and footer as class variables. All instances of MenuContainer will share them. You want

code:
class MenuContainer:
  def __init__(self, Settings = None):
    self.sidemenu = PageMenu()
    self.sidemenu.Items.append(MenuItem(Text="Home", URL="/"))
    ...

ATLbeer
Sep 26, 2004
Über nerd

JoeNotCharles posted:

This creates sidemenu, midmenu, topmenu and footer as class variables. All instances of MenuContainer will share them. You want

code:
class MenuContainer:
  def __init__(self, Settings = None):
    self.sidemenu = PageMenu()
    self.sidemenu.Items.append(MenuItem(Text="Home", URL="/"))
    ...

That was it... Working 12 hours today and my brain is fried... I need to blow something up tomorrow.

Lonely Wolf
Jan 20, 2003

Will hawk false idols for heaps and heaps of dough.

ATLbeer posted:

code:

class MenuItem:
	def __init__(self, Text = "", URL="", Current=False):
		self.Text = ""
		self.URL = ""
		self.Current = False
class PageMenu:
	def __init__(self, Enabled=False, Items=[]):
		self.Enabled = False
		self.Items = []


You're throwing all your parameters away and even with the scope issuse resolved it's not going to do anything. It should be self.Text = Text, etc.

Also, the official and idiomatic style is to only start names with capitals iff they are the names of classes.

bosko
Dec 13, 2006
Has anyone gotten PayPal IPN working with Python? For the life of me I can't figure out what I am doing wrong when I have simply taken the idea from another (working) script and used it in my own.

I am not getting errors, it just seems PayPal cannot verify my payment and therefore nothing is happening unless the user explicitly clicks on "Return to Merchant" which then everything is grand, but not every user clicks that link

This is a mix of django/python but the relevant stuff is in Python

PP_URL = https://www.paypal.com/cgi-bin/webscr

code:
newparams = {}
    for key in request.POST.keys():
        newparams[key] = request.POST[key]

    newparams['cmd'] = '_notify-validate'

    params = urlencode(newparams)

    req = urllib2.Request(PP_URL)
    req.add_header("Content-type", "application/x-www-form-urlencoded")
    fo = urllib2.urlopen(PP_URL, params)

    ret = fo.read()
    if ret != 'VERIFIED':
        return HttpResponse('Could not verify PayPal Payment')


# Other code to store information into cart

return HttpResponseRedirect('....') # Redirects the user if everything was A-OK
Any ideas what I could be doing wrong? Thanks in advance.

Adbot
ADBOT LOVES YOU

nonathlon
Jul 9, 2004
And yet, somehow, now it's my fault ...
What are people using for general HTML form generation? A lot of the more popular modules out there are tied to particular frameworks (e.g. zope.form, newforms). I really like formencode's validation and conversion but it doesn't generate forms (for good reasons) and has some oddities when handling arrays of fields. formbuild is supposed is okay, but again has a couple of odd design decisions.

  • Locked thread