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
Seaside Loafer
Feb 7, 2012

Waiting for a train, I needed a shit. You won't bee-lieve what happened next

Anyone know the core reason why 'self' must be the first arg in any class constructor or class method in python?

I can see one good usage:

code:
class sausage:
    def __init__(self, sausageType):
        self.sausageType = sausageType
There in the constructor I can say sausageType without having to use a class level variable.

I asked a guy I recently worked with and he said 'thats just how it is, deal with it'.

Seaside Loafer fucked around with this message at 07:28 on Feb 19, 2012

Adbot
ADBOT LOVES YOU

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
There's retroactive reasons, such as the fact that it tears down the walls between functions and methods, and allows things like classmethods/staticmethods without language features... but the actual history is much simpler than that: "Modula-2 did it that way".

That said, when you get to realize the simplicity of the mechanism, you'll see why it's a good thing. Also note that most languages work like this: in both .NET and Java (and ActionScript) the "this" parameter is passed as the first parameter so that they don't have to have two different opcodes for calling a method vs. a function, and as far as I know, all C++ implementations (all that count, gcc, clang, msvc++) do the same.

Simplest path to enlightenment: Go ahead and implement a few decorators that can handle both methods and functions and then get back to me.

Seaside Loafer
Feb 7, 2012

Waiting for a train, I needed a shit. You won't bee-lieve what happened next

Thanks man!

tef
May 30, 2004

-> some l-system crap ->
This (I believe) comes from the early design of python - http://python-history.blogspot.com/2009/02/adding-support-for-user-defined-classes.html

quote:

A major design constraint was that I didn’t want to add syntax for methods that differed from the syntax for functions. Refactoring the grammar and the byte code generator to handle such similar cases differently felt like a huge task. However, even if I was successful in keeping the grammar the same, I still had to figure out some way to deal with instance variables.

Pythons OO is really built around functions, rather than having methods. As a consequence, self is just another argument rather than a built-in.

Other consequences are:
code:
# you can access a method by the attribute to return a bound method that behaves like a function
x = foo.a 
x(1,2,3)

foo.a(1,2,3) 

# methods are stored as functions in classes
class Foo(object):
    def bar(self,x):
        return x

class Foo(object):
    pass

def bar(self, x):
    return x

Foo.bar = bar

# You can call methods directly from classes and provide a different self
f = Foo()
Foo.bar(f, 1)

# self is not magic and obeys normal scope rules
def somemethod(self, a,b):
    def callback(x): 
        self.oncallback(x)
    a.register(callback,b)

# and you can pass a method as a callback instead
    a.register(self.oncallback)
So mostly because it is less magic.

tef
May 30, 2004

-> some l-system crap ->

Suspicious Dish posted:

There's retroactive reasons, such as the fact that it tears down the walls between functions and methods, and allows things like classmethods/staticmethods without language features... but the actual history is much simpler than that: "Modula-2 did it that way".

I don't think this is true - As far as I am aware, Modula-2 did not have objects/classes. Modula-3 did influence the module system some, but its class system is quite distinct from python's mechanisms.

As mentioned in the link above, the retroactive reasons you suggest are in fact the primary motivating factors.

quote:

Simplest path to enlightenment: Go ahead and implement a few decorators that can handle both methods and functions and then get back to me.

Also: Reimplementing the classmethod/staticmethod decorators is a good approach to understanding python descriptors, which are lovely :3:

ufarn
May 30, 2009
I've never really done anything IO intensive work that uses os.path as well. I use the static blog generator blogofile, and I am trying to make sense of this tutorial.

This is basically what my directory looks like, irrelevant folders not listed:


_controllers
\-- blog
--- \-- __init__.py
--- \-- minify.py
static
\-- css
--- \-- style.css
--- \-- foo.css
--- \-- bar.css


And when the controllers are run in the blogofile build command, I get this folder in the directory which is the generated static site:


_site
\-- (...)
\-- static
--- \-- css
--- --- \-- style.css
--- --- \-- foo.css
--- --- \-- bar.css
_controllers
\-- blog
--- \-- __init__.py
--- \-- minify.py
static
\-- css
--- \-- style.css
--- \-- foo.css
--- \-- bar.css


I am trying to write a fairly simple controller that minifies my CSS files in static/css/ with cssmin that takes the CSS files there and minifies them, so I would ideally get this, when I build with blogofile:


_site
\-- (...)
\-- static
--- \-- css
--- --- \-- style.css
--- --- \-- style.min.css
--- --- \-- foo.css
--- --- \-- foo.min.css
--- --- \-- bar.css
--- --- \-- bar.min.css


Right now, I do have a script, but nothing happens when it is run during the build. bf.config.css_path refers to a defined directory for my stylesheets at static/css, defined as os.path.join("static", "css").

code:
import os.path

from cssmin import cssmin

from blogofile.cache import bf


config = {"name"        : "Minify",
          "priority"    : 40.0}

def run():
    # define stylesheets as retrieved stylesheets
    stylesheets = read_stylesheets()
    # build minified stylesheets from retrieved stylesheets
    build_mins(stylesheets)

def read_stylesheets():
    # retrieve all .css files and return them
    return [s for s in bf.config.css_path if s.lower().endswith(".css")]

def build_mins(stylesheets):
    # define css_dir as _site/static/css/
    css_dir = os.path.join("_site", bf.config.css_path)
    for s in stylesheets:
        # for the stylesheet _site/static/css/foo.min.css
        with open(css_dir + os.path.splitext(s)[0] + "min.css", "w") as f:
            # use the minified code from stylesheet static/css/foo.css
            f.write(cssmin(open(s).read()))
I think this has more to do with my Python than blogofile, but I could be wrong. Just let me know if anything there jumps out as egregiously wrong.

ufarn fucked around with this message at 16:28 on Feb 19, 2012

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.
Deliberately try to break you code and see what happens, or write some tests.
Are you sure blogofile is actually calling the code?

ufarn
May 30, 2009

Maluco Marinero posted:

Deliberately try to break you code and see what happens, or write some tests.
Are you sure blogofile is actually calling the code?
Positive. It threw errors about some typos I had made. Its controller calls the scripts, but no minified files show up, so I was wondering if I was using os.path incorrectly, which seems like the best bet.

Blogofile by default uses controllers to generate templates, not things like altered stylesheets and images, so I had to try to write it my own quirky way.

I'll see if I can write something to log the behavior.

EDIT: Added some basic comments to the code.

ufarn fucked around with this message at 16:29 on Feb 19, 2012

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.

ufarn posted:

I'll see if I can write something to log the behavior.
If you haven't already learned about it, try using

http://docs.python.org/library/pdb.html
pre:
import pdb; pdb.set_trace()
Rough and ready way to drop into a debugging session so you can test what variables are set, perform the actions yourself and test results, etc.

Better to use with a proper test framework though.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

tef posted:

I don't think this is true - As far as I am aware, Modula-2 did not have objects/classes. Modula-3 did influence the module system some, but its class system is quite distinct from python's mechanisms.

Ah, I did mean Modula-3. And while the class system is quite distinct, the name self appears right in the example.

I can't find it now, but I remember reading a python-list post that said that the name "self" was chosen over "this" because Modula-3 used the term "self". Of course that's a slightly different question than what Seaside Loafer was asking, but I believe I'm well-grounded in saying that Modula-3 had at least some inspiration on the object system.

ufarn
May 30, 2009
Can someone explain why I can't get footnotes to work in Markdown?

code:
pip install markdown
code:
>>> from markdown import markdown
>>> markdown(extensions=['footnotes'], text="foo[^1] \n\n [1]: bar")

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\site-packages\markdown-2.0.3-py2.7-win32.egg\markdown\__
init__.py", line 598, in markdown
    return md.convert(text)
  File "C:\Python27\lib\site-packages\markdown-2.0.3-py2.7-win32.egg\markdown\__
init__.py", line 395, in convert
    newRoot = treeprocessor.run(root)
  File "C:\Python27\lib\site-packages\markdown-2.0.3-py2.7-win32.egg\markdown\tr
eeprocessors.py", line 271, in run
    text), child)
  File "C:\Python27\lib\site-packages\markdown-2.0.3-py2.7-win32.egg\markdown\tr
eeprocessors.py", line 95, in __handleInline
    data, patternIndex, startIndex)
  File "C:\Python27\lib\site-packages\markdown-2.0.3-py2.7-win32.egg\markdown\tr
eeprocessors.py", line 219, in __applyPattern
    node = pattern.handleMatch(match)
  File "C:\Python27\lib\site-packages\markdown-2.0.3-py2.7-win32.egg\markdown\ex
tensions\footnotes.py", line 269, in handleMatch
    a.text = str(self.footnotes.footnotes.index(id) + 1)
  File "C:\Python27\lib\site-packages\markdown-2.0.3-py2.7-win32.egg\markdown\od
ict.py", line 120, in index
    return self.keyOrder.index(key)
ValueError: u'1' is not in list
What am I missing here?

ufarn fucked around with this message at 16:47 on Feb 21, 2012

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.
Need the footnote at the bottom to be [^l] as well. Using brackets without the caret results in a reference link rather than footnote.

http://freewisdom.org/projects/python-markdown/Footnotes

Maluco Marinero fucked around with this message at 17:15 on Feb 21, 2012

ufarn
May 30, 2009

Maluco Marinero posted:

Need the footnote at the bottom to be [^l] as well. Using brackets without the caret results in a reference link rather than footnote.

http://freewisdom.org/projects/python-markdown/Footnotes
I'm the biggest idiot in the world. Thanks, man.

Crankit
Feb 7, 2011

HE WATCHES
I was wondering about GUI apps in python, all the tutorials I've seen seem to concentrate on commandline apps. I've done a couple of searches to see if there are any RAD IDEs as I'm used to delphi, but are apps developed in these then incompatible with standard python and each other?

What I'm asking really is what's the most straightforward way to make guis, but also would using IronPython or Jython lead to me being annoyed 12 months down the road?

ThreeHams
Sep 28, 2005

Ride the pig!

Crankit posted:

I was wondering about GUI apps in python, all the tutorials I've seen seem to concentrate on commandline apps. I've done a couple of searches to see if there are any RAD IDEs as I'm used to delphi, but are apps developed in these then incompatible with standard python and each other?

What I'm asking really is what's the most straightforward way to make guis, but also would using IronPython or Jython lead to me being annoyed 12 months down the road?

wxPython is probably the most mature cross-platform GUI kit. That said, it's a bit of a mess, and doesn't follow most Python conventions (keep it constrained to its own class, and it should be fine). Documentation used to be godawful, but it's gotten much better over the last couple years.

wxGlade is a graphical tool for building the wx code, but hasn't been updated in at least a year - there are probably much better ones out there now.

http://zetcode.com/wxpython/ is a good place to start for a tutorial, much better than the official ones.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Crankit posted:

I was wondering about GUI apps in python, all the tutorials I've seen seem to concentrate on commandline apps. I've done a couple of searches to see if there are any RAD IDEs as I'm used to delphi, but are apps developed in these then incompatible with standard python and each other?

What I'm asking really is what's the most straightforward way to make guis, but also would using IronPython or Jython lead to me being annoyed 12 months down the road?

In the past couple months I went through the same thing. I tested out most of the major frameworks and ended up using PySide. You can use QtDesigner with it.

Ither
Jan 30, 2010

Hi, everybody. I have a question.

I'm using Phylonet, a java program, to calculate the Robinson-Fould metric for phylogenetic trees.

Via the command line, Phylonet can calculate the RF two ways: 1)By getting the trees from a file or 2)By writing the trees in the command window which requires three returns

I wrote python code that does the first method:

code:
import subprocess

def calculateRF():


    cmd = "java -jar phylonet_v2_4.jar rf -m X.txt -e Y.txt"
    direc = "C:\\phylo"

    output = subprocess.check_output(cmd, cwd=direc)
    print(output)
But I can't figure out how to do the second. Help? I suspect the returns are part of the problem

Capnbigboobies
Dec 2, 2004

Crankit posted:

I was wondering about GUI apps in python, all the tutorials I've seen seem to concentrate on commandline apps. I've done a couple of searches to see if there are any RAD IDEs as I'm used to delphi, but are apps developed in these then incompatible with standard python and each other?

What I'm asking really is what's the most straightforward way to make guis, but also would using IronPython or Jython lead to me being annoyed 12 months down the road?
I am a novice programmer and have tried ironpython, wxpython, pyside and others. I liked pyside the best. Pyside code is very similar to pyqt. It also uses the lgpl which is nice.

The documentation is decent. It works well and looks nice. It also has a designer that is light years better than wxglade. You can rapidly whip up a nice interface then code. It sure beats defining every element by hand. Also pyside follows python conventions a bit better than wxpython.

I experimented with a simple, very lovely rss reader I made using ironpython,(using wpf for the GUI stuff) wxpython and pyside. Pyside used the least amount of ram. Also it was trivial to use pyInstaller to roll my program into a portable exe.

Seaside Loafer
Feb 7, 2012

Waiting for a train, I needed a shit. You won't bee-lieve what happened next

Crankit posted:

I was wondering about GUI apps in python, all the tutorials I've seen seem to concentrate on commandline apps. I've done a couple of searches to see if there are any RAD IDEs as I'm used to delphi, but are apps developed in these then incompatible with standard python and each other?

What I'm asking really is what's the most straightforward way to make guis, but also would using IronPython or Jython lead to me being annoyed 12 months down the road?
wxWidgets works. That said the available design tools are poo poo, dont expect MS Visual Studio. What I did was use a couple of the design tools to draw some controls, read the code they deliver, then just use pure code. It was obvious within days that using the drawing controls type tools for it would be more effort than just coding it (once you have got how it works).

So yeah, get wxWidgets, get a freeware design tool for it, play with it so you got some sample code, ditch the tool, go from there.

OnceIWasAnOstrich
Jul 22, 2006

Ither posted:


But I can't figure out how to do the second. Help? I suspect the returns are part of the problem

By returns I am assuming you mean you need to input things to STDIN and hit the return button. You will need to abandon the check_output() method and directly use a Popen object and the communicate() method.

Something like:

code:
import subprocess

cmd = "java -jar phylonet_v2_4.jar rf"
direc = "C:\\phylo"
model_file = "test.mt"
tree_file = "test.tr"
output_file = "test.txt"

p = subprocess.check_output(cmd, cwd=direc,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
print(p.communicate(model_file+'\n'+tree_file+'\n'+output_file+'\n')[0])

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I wonder if there are an internals people that can tell me the types being used technically when passing a class around, not an object, and if I should be using type(class) instead. I'm trying to make this cooperate with Boost.Python, and I think I've stepped outside the normal domain of their cplusplus-sig mailing list. Say I have a list of objects implementing an interface, of which some could be a Python implementation. I was to expose a method that, given a class type, can determine if something in that list is that class specifically. Note--not that specific object!

Say I have class Foo. If I were to do container.Has(Foo), I think I get something different from container.Has(type(Foo)). I figure the latter is normally what I'd want to use. It looks like the former is normally a Boost.Python.class and the latter comes up as "type" in Python in the signature, but it doesn't mate up with a C++ function that's using PyTypeObject*, so what is the underlying C structure for "type" in Python?

Ither
Jan 30, 2010

OnceIWasAnOstrich posted:

By returns I am assuming you mean you need to input things to STDIN and hit the return button. You will need to abandon the check_output() method and directly use a Popen object and the communicate() method.

Something like:

code:
import subprocess

cmd = "java -jar phylonet_v2_4.jar rf"
direc = "C:\\phylo"
model_file = "test.mt"
tree_file = "test.tr"
output_file = "test.txt"

p = subprocess.check_output(cmd, cwd=direc,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
print(p.communicate(model_file+'\n'+tree_file+'\n'+output_file+'\n')[0])


Thank you.

I ended up solving the problem using temporary files, but I'll see if this method works too.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb
I've decide to re-write a PHP webapp in Python since the PHP code is crap and I've been wanting to learn Python for awhile anyways. I was going to give Flask & SQLAlchemy a shot, seems to offer a bit more flexibility over something like Django. Any advice before I dive in?

Johnny Cache Hit
Oct 17, 2011

fletcher posted:

I've decide to re-write a PHP webapp in Python since the PHP code is crap and I've been wanting to learn Python for awhile anyways. I was going to give Flask & SQLAlchemy a shot, seems to offer a bit more flexibility over something like Django. Any advice before I dive in?

Flask is pretty cool. But so is Django, and you'll probably find it faster to get moving quickly under Django because some of the nice built-ins it gives you.

Just be sure you're not falling into the trap of thinking that you'll need more flexibility without really thinking about what you're trying to do, because often times your problem isn't as hard as you'd think.

JetsGuy
Sep 17, 2003

science + hockey
=
LASER SKATES
Ok, I figure I'm doing something wrong with the style of how this should be coded, and I'm just having trouble googling the right keywords to determine the correct way to deal with this.

So I wrote a class that contains multiple functions, but the ultimate goal of this class is to create a data file for me (using these multiple functions in the class).

The code starts with something like this:

code:
class makedata:
     def __init__(self,var1,var2,var3,var4=default):
          self.var1=str(var1)
          self.var2=str(var2)
          self.var3=numpy.float(var3)

#####OTHER CODE#######

     def main(self):
          ###runs other functions and writes a data file
I wrote another script to run this a bunch of times to make all the data files I want. For example:

code:
import makedata as makedata
##other code##
var3=num.array([a,b,c])
for i in num.arange(0,len(var3),1):
     data=makedata.makedata(var1,var2,var3[i])
     data.main()
My thought is that by defining "data" each time I go through that loop, it should re-initialize the class, and output the correct data into a new data file.

The strange thing is that it seems to be half-working. For example, I am getting different output files, which are named as if they are for the different instances of var3. However, the output data that are written to them are all the same.

My suspicion is that I'm doing something wrong with __init__. I also realize this is a fairly newbie question, so I'm sorry for how clueless I may be seeming right now. :(

Hed
Mar 31, 2004

Fun Shoe
I've never used NumPy but it looks like what you're doing should work. Can you look closer at the way you're writing out files?

Lysidas
Jul 26, 2002

John Diefenbaker is a madman who thinks he's John Diefenbaker.
Pillbug

JetsGuy posted:

code:
import makedata as makedata
##other code##
var3=num.array([a,b,c])
for i in num.arange(0,len(var3),1):
     data=makedata.makedata(var1,var2,var3[i])
     data.main()

:3: Did you learn to program in C? Unless you have a good reason not to (and in the code you posted, you don't), you should iterate directly over the values in a container:

code:
var3 = num.array([a, b, c])
for value in var3:
     data = makedata.makedata(var1, var2, value)
     data.main()
Also, learn you some PEP8.


More generally, can you post enough code so that we can try to run this ourselves? What you posted looks like it'll work, so it's likely that there are problems lurking in what you didn't post.

JetsGuy
Sep 17, 2003

science + hockey
=
LASER SKATES

Hed posted:

I've never used NumPy but it looks like what you're doing should work. Can you look closer at the way you're writing out files?

------ I originally had something to say about how I was looking there, it's happening slightly before that, as I've now found.

Lysidas posted:

:3: Did you learn to program in C? Unless you have a good reason not to (and in the code you posted, you don't), you should iterate directly over the values in a container:

code:
var3 = num.array([a, b, c])
for value in var3:
     data = makedata.makedata(var1, var2, value)
     data.main()

Heh, I guess the first language I ever scripted in was Perl (shudder), and I haven't looked at it in 10 years. I pretty much taught myself python when I was in a computational physics course in grad school. I guess one issue that comes with that is that you learn how to code from people who pretty much live in FORTRAN and IDL.

Also, the only real reason I do things like that is it's easier for me to think of arrays in terms of their indicies. I generally write huge arrays of data, and it's just easier for me to visualize when I'm writing routines.

Yeah, I don't need it here though.

quote:

Also, learn you some PEP8.

:laugh: Ok, I'll take a look.


quote:

More generally, can you post enough code so that we can try to run this ourselves? What you posted looks like it'll work, so it's likely that there are problems lurking in what you didn't post.

I can't post the whole thing, unfortunately. In any case, it would require a number of large .fits files to run.

**********

However, I have found where the problem is occurring.

The main() function within the class makedata calls another function that prepares the data to be written. What that function does is bins the data by time. Here's the snippet:

code:
def main(self):
        ----snip----
        event_master=num.sort(event_master)

        print self.Tbinning
        
        master_LC=self.T_bin(event_master)
        ----snip----
(where event_master is a 1D array of event times over multiple detectors)

Here, self.Tbinning reports the correct value for each iteration run by the wrapper script.

code:
def T_bin(self,events,t_details=[None,None,None]):
        if t_details==[None,None,None]:
            t_details[0]=self.Tmin
            t_details[1]=self.Tmax
            t_details[2]=self.Tbinning

        print t_details[2]
...but here, moments later, this value does not. I see no reason for why self.Tbinning would reset itself somehow.

FAKE EDIT: Oh, wait, it must be that t_details is remembering its value for the previous iteration from the wrapper, so it doesn't reset with the new Tbinning. Why would that be? Shouldn't it forget it that variable after the definition finishes?

EDIT2:

I "fixed" it by just having the main function intentionally pass new values for t_details to the T_bin function every time. I'm still curious as to why it wasn't able to pull them down itself through the class variables though.

JetsGuy fucked around with this message at 01:12 on Feb 24, 2012

Reformed Pissboy
Nov 6, 2003

JetsGuy posted:

code:
def T_bin(self,events,t_details=[None,None,None]):
        if t_details==[None,None,None]:
            t_details[0]=self.Tmin
            t_details[1]=self.Tmax
            t_details[2]=self.Tbinning

        print t_details[2]
...but here, moments later, this value does not. I see no reason for why self.Tbinning would reset itself somehow.

I'm fairly sure you've hit a classic Python gotcha: mutable default arguments. The link explains it better than I can, but basically after multiple calls, t_details is no longer going to default to [None, None, None], but to whatever stuff you've assigned to it within the function.

Try making t_details default to None (or require it be passed in), or not modifying t_details within that function, or even pass it as a tuple ( (None, None, None) ) which is non-mutable. I bet you'll see the results you're expecting.

JetsGuy
Sep 17, 2003

science + hockey
=
LASER SKATES

Harm Barn Gumshoe posted:

I'm fairly sure you've hit a classic Python gotcha: mutable default arguments. The link explains it better than I can, but basically after multiple calls, t_details is no longer going to default to [None, None, None], but to whatever stuff you've assigned to it within the function.

Try making t_details default to None (or require it be passed in), or not modifying t_details within that function, or even pass it as a tuple ( (None, None, None) ) which is non-mutable. I bet you'll see the results you're expecting.

Whoa. This is very interesting, and really contradicts what I expected. As the page describes, I was operating under the assumption that all values under a defined function will be reset as they are local to that function.

That is just very strange behavior to me that a list will retain its memory within the function. :psyduck: I get that it's a feature, but :psyduck::psyduck::psyduck:

Indeed, the way I fixed it was to take out the default definition of [None,None,None], and just require that an array of the values I need are passed to it when the function is called. This fixed the problem.

good jovi
Dec 11, 2000

JetsGuy posted:

Whoa. This is very interesting, and really contradicts what I expected. As the page describes, I was operating under the assumption that all values under a defined function will be reset as they are local to that function.

That is just very strange behavior to me that a list will retain its memory within the function. :psyduck: I get that it's a feature, but :psyduck::psyduck::psyduck:

Indeed, the way I fixed it was to take out the default definition of [None,None,None], and just require that an array of the values I need are passed to it when the function is called. This fixed the problem.

The difference is that objects defined inside a function definition are not "under" that function. They're in the same scope (sort of) as the function itself.

NadaTooma
Aug 24, 2004

The good thing is that everyone around you has more critical failures in combat, the bad thing is - so do you!
This is an interesting topic, and it motivated me to go hunt down the best explanation as to exactly why mutable default arguments aren't a good idea. It's been a few years! The best I've ever found is from Frederik Lundh: http://effbot.org/zone/default-values.htm. Short version: Default parameters are evaluated each time a function is *created* (via a call to "def"), rather than each time a function is *called*.

:ninja: And yeah, I realize this has been answered, but it's neat stuff anyway. :ninja:

NadaTooma fucked around with this message at 18:27 on Feb 24, 2012

geonetix
Mar 6, 2011


I just tried it:

code:
>>> def mutable(argument=[1,2,3,4]):
...     return argument
... 
>>> mutable()
[1, 2, 3, 4]
>>> _.append(5)
>>> mutable()
[1, 2, 3, 4, 5]
Amazing. I never ran into this nor was I aware of it. The explanation seems logical, but counters everything I'd expect.

Computer viking
May 30, 2011
Now with less breakage.

geonetix posted:

I just tried it:

code:
>>> def mutable(argument=[1,2,3,4]):
...     return argument
... 
>>> mutable()
[1, 2, 3, 4]
>>> _.append(5)
>>> mutable()
[1, 2, 3, 4, 5]
Amazing. I never ran into this nor was I aware of it. The explanation seems logical, but counters everything I'd expect.

My thoughts exactly - never run into it, can see that it could be useful, and it's definitely a POLA violation. Oh well, you really do learn something new every day.

JetsGuy
Sep 17, 2003

science + hockey
=
LASER SKATES
:3: cool, I helped people learn something!

The Gripper
Sep 14, 2004
i am winner

Computer viking posted:

My thoughts exactly - never run into it, can see that it could be useful, and it's definitely a POLA violation. Oh well, you really do learn something new every day.
I understand why they're there, from a technical standpoint, but any of the uses I can think of are probably made more complicated by making use of their mutability.

An example like this, a function which returns a list of the digits in an integer:
code:
def IntToList(x, acc=[]):
    if x < 0: x = abs(x)
    if x % 10 == 0:
	return acc
    acc.insert(0, x % 10)
    return IntToList(x/10,acc)
can use the mutable argument as an accumulator, which works as you'd expect:
code:
>>> IntToList(1234)
[1, 2, 3, 4]
but this moves the bulk of the programs state into the function (which may not be useful to you), making it hard to keep track of vs. just keeping the state separately.
code:
#call 2
>>> IntToList(-12345)
[1, 2, 3, 4, 5, 1, 2, 3, 4]
If they could be used more similarly to curried functions in functional languages (maybe they can, I'm sure I haven't exhausted every possibility) then I could see some good uses, but as it is actually making use of it looks like would cause more problems than it solves (and in the above example, calling x = IntToList(12345, []) is equivalent and only three characters longer).

Computer viking
May 30, 2011
Now with less breakage.

Agreed, it doesn't seem like it solves any problems that couldn't be done equally well in a more explicit way, while it sets an unexpected trap (POLA and all that). Ah well, at least there's an implementation explanation for it that makes some technical sense.

Jonnty
Aug 2, 2007

The enemy has become a flaming star!

Computer viking posted:

Agreed, it doesn't seem like it solves any problems that couldn't be done equally well in a more explicit way, while it sets an unexpected trap (POLA and all that). Ah well, at least there's an implementation explanation for it that makes some technical sense.

This seems to come up a lot; perhaps it's worth mentioning in the OP?

Look Around You
Jan 19, 2009

I guess I have a question. Has anything replaced PyGame? The site is in shambles and it's spammed and the wiki is being auto-trashed by bots advertising for stupid poo poo. It looks like Cocos2d is good and does a lot of the same stuff and is actually currently being worked on... is this what people are using now?

Adbot
ADBOT LOVES YOU

The Gripper
Sep 14, 2004
i am winner

Look Around You posted:

I guess I have a question. Has anything replaced PyGame? The site is in shambles and it's spammed and the wiki is being auto-trashed by bots advertising for stupid poo poo. It looks like Cocos2d is good and does a lot of the same stuff and is actually currently being worked on... is this what people are using now?
There aren't a lot of alternatives, mainly because PyGame's audience tended to be educational learning python, learning game logic or python-for-the-sake-of-it people. Not meaning to trash PyGame, but it does lack the commercial developer support that a lot of other open-source projects have, which limits the resources out there for people who have gone through the tutorials and need guidance in real-world applications.

Your options are likely PyGlet and PyOpenGL as alternatives, but both of those haven't had significant releases in the last year and it's altogether possible that they have no active developers, currently. If you have specific questions it might be worth checking the PyGame IRC channels and asking around.

  • Locked thread