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
SlightlyMadman
Jan 14, 2005

Bonus posted:

code:
for field in ["att1", "att2", "att3"]:
  if getattr(object, field) == 0:
    setattr(object, field, "")

Couldn't he also replace the first line with:
code:
for field in vars(object):
Or would that be a problem because it lists out other stuff you don't want to mess with? I'm pretty new to reflection in python, but it seems incredibly powerful (almost too powerful).

Adbot
ADBOT LOVES YOU

hey mom its 420
May 12, 2007

He could, but somehow I feel the Python mantra of explicit is better than implicit should be taken into account here.

SlightlyMadman
Jan 14, 2005

Bonus posted:

He could, but somehow I feel the Python mantra of explicit is better than implicit should be taken into account here.

I'll definitely have te defer to you there, since I come from much more of a heavy-handed java background. The reason I pointed it out is that it avoids magic strings, and if he ever adds more fields to the object he doesn't have to make the change in two places.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

SlightlyMadman posted:

I'll definitely have te defer to you there, since I come from much more of a heavy-handed java background. The reason I pointed it out is that it avoids magic strings, and if he ever adds more fields to the object he doesn't have to make the change in two places.

The decorator posted above does this without also making every variable available, even those the designer never considered.

Colorblind Pilot
Dec 29, 2006
Enageg!1

Bonus posted:

Python supports functions as first-class objects. So one way to do it would be this.
code:
>>> def foo(x):
...   print 'haha %s' % x
...
>>> def bar():
...   print 'hoho'
...
>>> my_func_dict = {'the_foo':foo, 'the_bar':bar}
>>> my_func_dict['the_foo']('blah')
haha blah

This is exactly what I'm looking for, thank you.

Sparta
Aug 14, 2003

the other white meat
Apologies if this has been answered already, but there's a lot here to wade through.

I want to learn Python (in fact, I'm going to have to learn it). I have a little programming background. I got through 3 quarters of Computer Science, in which I mainly mastered C, and struggled tremendously with Java.

I have worked with PHP, and although I'm not really a great coder, if I need to figure out a problem, I can most likely find myself a solution.

I love procedural programming, it makes sense to me, but I keep hearing about how great Python is (and about OOP). Is there a tutorial/book out there that is good at teaching me how to code Python when I do have some programming experience, but only on the procedural end?

duck monster
Dec 15, 2004

SlightlyMadman posted:

I'll definitely have te defer to you there, since I come from much more of a heavy-handed java background. The reason I pointed it out is that it avoids magic strings, and if he ever adds more fields to the object he doesn't have to make the change in two places.

It avoids magic strings, but endangers the whole operation of magic variables. Theres a lot of __crufty__ __magical__ __stuff__ __under__ __the__ __hood__ that could get caught up in that blender!

duck monster
Dec 15, 2004

Sparta posted:

Apologies if this has been answered already, but there's a lot here to wade through.

I want to learn Python (in fact, I'm going to have to learn it). I have a little programming background. I got through 3 quarters of Computer Science, in which I mainly mastered C, and struggled tremendously with Java.

I have worked with PHP, and although I'm not really a great coder, if I need to figure out a problem, I can most likely find myself a solution.

I love procedural programming, it makes sense to me, but I keep hearing about how great Python is (and about OOP). Is there a tutorial/book out there that is good at teaching me how to code Python when I do have some programming experience, but only on the procedural end?

The tutorial is always the place to start for python. The one on the site is actually very good. It wont take you more than a day, and you'll get quite deep into pythonn, certainly enough to fend for yourself assuming a basic programing competency (which you have if you can do C)

The object oriented stuff, uh I dunno man, just think of them as structs with functions inside them, if the analogy of 'balls of data and code that send messages to each other' hurts the head too much. The structs with functions inside them is a bit of a cheap description because it doesnt capture the capacities, but its a start.

OO almost always comes to people in one big "ah ha!" moment when suddenly they just 'get it' all at once, a bit like how database normalisation starts off frusturatingly wierd, and then suddenly just makes sense to people in one hit.

nonathlon
Jul 9, 2004
And yet, somehow, now it's my fault ...

Sparta posted:

I want to learn Python (in fact, I'm going to have to learn it). I have a little programming background. I got through 3 quarters of Computer Science, in which I mainly mastered C, and struggled tremendously with Java.

I have worked with PHP, and although I'm not really a great coder, if I need to figure out a problem, I can most likely find myself a solution.

I love procedural programming, it makes sense to me, but I keep hearing about how great Python is (and about OOP). Is there a tutorial/book out there that is good at teaching me how to code Python when I do have some programming experience, but only on the procedural end?

I wouldn't get too hung up on OOP - you can program procedurally in Python until you get the idea of objects. And then you will wonder how you ever did without them. But if you think of objects as just smart structs, records with functions attached, that will get you a long way.

A good place to start learning is Dive Into Python and/or How to think like a Computer Scientist. Both are free on the web. I'd suggest doing a few different tutorials, to get different points of view on things.

m0nk3yz
Mar 13, 2002

Behold the power of cheese!

outlier posted:

I wouldn't get too hung up on OOP - you can program procedurally in Python until you get the idea of objects. And then you will wonder how you ever did without them. But if you think of objects as just smart structs, records with functions attached, that will get you a long way.

A good place to start learning is Dive Into Python and/or How to think like a Computer Scientist. Both are free on the web. I'd suggest doing a few different tutorials, to get different points of view on things.

For a long time, I did procedural programming in Python - then one day, the sky opened up and I just "got oop" - just start with what you know and don't sweat getting everything down. You'll self-evolve and over time, your code will improve. Just always challenge yourself.

tef
May 30, 2004

-> some l-system crap ->
OOP is fun and games but functional style programming in python is where the real fun is at.

Generators and list comprehensions are both awesome and powerful.

Pivo
Aug 20, 2004


tef posted:

OOP is fun and games but functional style programming in python is where the real fun is at.

At my school we did our first two CS courses in Scheme, and for the most part without mutation.

This made me appreciate even more how flexible Python is. If you've ever wanted to double the number of ways you know how to solve a particular problem, try Scheme.

m0nk3yz
Mar 13, 2002

Behold the power of cheese!

tef posted:

OOP is fun and games but functional style programming in python is where the real fun is at.

Generators and list comprehensions are both awesome and powerful.

But I use OOP and Generators/List Comps together. It's like a functionallyOOP bastard child!

hey mom its 420
May 12, 2007

Yeah, I prefer an OOP/functional combination as well. And when I mean OOP, I don't mean Java-style OOP where your program is basically a big inheritance tree, I just mean taking advantage of the fact that everything is an object but avoiding too much inheritance.

tef
May 30, 2004

-> some l-system crap ->
I really like being able to choose when to make things classes and when to make things functional style.

In the recent project at work, i've used a mixture of composition and inheritance in the objects, and functions for other parts.


Part of me wonders about prototypes in python :gay:

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

tef posted:

Part of me wonders about prototypes in python :gay:

http://notcharles.wordpress.com/2008/04/18/advogato-1/

bitprophet
Jul 22, 2004
Taco Defender

Bonus posted:

Yeah, I prefer an OOP/functional combination as well. And when I mean OOP, I don't mean Java-style OOP where your program is basically a big inheritance tree, I just mean taking advantage of the fact that everything is an object but avoiding too much inheritance.

Python-style OOP is definitely the better way to think about the paradigm, IMHO. It's simple enough to understand and use, and extremely powerful/flexible, without going overboard "just because OOP > *" like Java seems to. That's really Python in a nutshell, to me: everything you need, nothing you don't.

I'm still enjoying learning Ruby and Rails, but the more Ruby I learn the more I <3 Python. For example, in Ruby, attempting to reference a "normal" variable (e.g. foo) that doesn't exist, will throw an exception, as you'd expect. However! Attempting to reference an instance variable (e.g. @foo) that doesn't exist, will silently act as if it were nil (None).

So, incredibly hard to diagnose bugs ("Goddammit, why is this thing nil?! I know I assigned to it right here and my print statement shows it plain as day!!") become a simple one-character typo/mistake away. :waycool: Reminds me of PHP and its tendency to swallow errors whole. Friggin' sigils....Ruby's about 1/2 Perl, and based on that I have to say Perl is a poor role model :eng99:

Anyway, all that to say that this sort of thing helps me understand Guido's emphasis on keeping the language as spare as possible.

king_kilr
May 25, 2007
I used pyprocessing(aka multiprocessing) this weekend and it was really great to work with, I managed to offload all the simulations(aka computationally expensive work) to another process in hardly any work, just set up a pipe to communicate and set the process off, you can see the what change I made to made for this to happen here: http://github.com/alex/election-sim/commit/cc93df649d1295deab96f1f1ab1ff709e8b0f391

m0nk3yz
Mar 13, 2002

Behold the power of cheese!

king_kilr posted:

I used pyprocessing(aka multiprocessing) this weekend and it was really great to work with, I managed to offload all the simulations(aka computationally expensive work) to another process in hardly any work, just set up a pipe to communicate and set the process off, you can see the what change I made to made for this to happen here: http://github.com/alex/election-sim/commit/cc93df649d1295deab96f1f1ab1ff709e8b0f391

Yay! I'm glad it worked for you

LuckySevens
Feb 16, 2004

fear not failure, fear only the limitations of our dreams

noob question time again, since the last answers I got were pretty darn good :)

I'm trying to write a quick function to sort and return filenames in a directory by order of file extension. I tinkered myself for a little while but couldn't get anything to work cleanly, so I did some google cheating and found this:

code:
def cmp_extension(path0, path1):
     return cmp(os.path.splitext(path0)[1], os.path.splitext(path1)[1])

def print_dir_by_ext(dir_path):
     for name in sorted(os.listdir(dir_path), cmp_extension):
           print os.path.join(dir_path, name)
Of course, when inputting the dir I want to evaluate, it returns a perfect output. The only problem is, I don't quite understand exactly how this is work, I usually like to chart it in my mind how the input data is bouncing and for some reason this simple sorter function is doing it to me. I see that for every path/file we pull from an os.listdir on the dir_path we provide is being sorted, by how does cmp_extension fit into what is going on? os.path.splitext is obviously spliting the dir and file extension, and then it gets rebuilt before printing, but what is the path0, path1 values and where are they coming from? Such a noob :(

jonypawks
Dec 1, 2003

"Why didn't you tell me you were the real Snake?" -- Ken

LuckySevens posted:

Sorting question

The optional second argument for the sorted function, is the function that will be used to determine if an object in the sequence is <, =, or > another object. So cmp_extension is being used as this comparison function for sorted. Every time the sorted function needs to compare two of the elements during it's sorting process, it will call cmp_extension with two arguments, each being an element of the list we're sorting (in this case, the list returned by the os.listdir call).

So, cmp_extension's arguments are going to be filenames from the directory provided. First thing we do is use os.path.splitext to separate the filename and extension, which can be easily demonstrated with the python shell:

code:
>>> import os
>>> os.path.splitext('archive.tar')
('archive', '.tar')
>>> os.path.splitext('archive.tar')[1]
'.tar'
After we've grabbed each of the file extensions using splitext, we pass them to the cmp function and return the result. We do this because cmp can already handle comparing strings, so we take advantage of this built-in function.

I hope this explanation helps you out.

tef
May 30, 2004

-> some l-system crap ->

LuckySevens posted:

Of course, when inputting the dir I want to evaluate, it returns a perfect output. The only problem is, I don't quite understand exactly how this is workfore printing, but what is the path0, path1 values and where are they coming from? Such a noob :(

As mentioned earlier, sort takes an optional comparison function. In your case the comparison function compares the extentions. In the case below, sort uses reverse_cmp to compare numbers.

code:
def reverse_cmp(a,b):
    return cmp(a,b)

print sorted([1,9,3,5,6,7,3,2,3], cmp=reverse_cmp)
cmp is a function that takes two arguments and returns -1, 0, or 1 if a < b , a == b, or a > b respectively. sort takes an argument called cmp that it expects to behave in the same way.

However, it is often better to do a 'decorate-sort-undecorate' or a 'schwartzian-transform', than to have a complex comparison.

Instead of extracting the file extention for every comparison, we extract it once per filename and sort on that list instead.

For example, to sort a list of strings by their length, we 'decorate' it into a list of pairs:

code:
text = ['aaaaa','bbb','cccc','dd','e','fffff','gg']

tmp_text = []

for t in text:
    tmp_text.append( (len(t,t) )
tmp_text now contains [(5,'aaaaa'), (3,'bbb'),.....]

Then we sort by the first pair member:

code:
def cmp_first(a,b):
    return cmp(a[0],b[0])

print sorted(tmp_text, cmp=cmp_first)
Finally, we just 'undecorate' the list to remove the lengths (no code for this one, i'm lazy)

This is such a common idiom - preprocessing the keys and sorting by them - that sort takes an optional argument called key that takes a function to do this.

code:
print sorted(['aaaaa','bbb','cccc','dd','e','fffff','gg'], key=len)
So, for your original example, here is sort using the file extention as the key to sort on:

code:
import os.path

def get_file_ext(filename):
    return os.path.splitext(filename)[1]

print sorted(['foo.txt','bar.pdf','baz.doc'], key=get_file_ext)
I would advocate using the latter over the example you gave :)

tef fucked around with this message at 11:10 on Oct 28, 2008

LuckySevens
Feb 16, 2004

fear not failure, fear only the limitations of our dreams

At first I read the explanation and I was like "wow programmer guys love talking about how they'd do it", but by breaking the problem down into a different method its helped me think and understand whats going on. I was a little bit clueless on the sorted() function parameters and its starting to click now. Very cool how much versatility (and shortcuts) inbuilt functions can have.

Thanks guys, and once again, such a good explanation there may be another q soon :q:

inveratulo
May 14, 2002
wat
Okay so I need to create and use a multi-dimensional array of unknown size.
To create, I am doing:
code:
myArray = [[]]
But I am not sure how to append my data to this structure?

No Safe Word
Feb 26, 2005

inveratulo posted:

Okay so I need to create and use a multi-dimensional array of unknown size.
To create, I am doing:
code:
myArray = [[]]
But I am not sure how to append my data to this structure?

Depends on what you want to do. If you're going to be doing math-like stuff, save yourself a headache and just start with NumPy from the get-go:
http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html

Otherwise, you can just start with a list, insert/append a new list, and so on.
code:
In [1]: myArray = []

In [2]: myArray.append([1,2,3])

In [3]: myArray.append([1,3,5])

In [4]: myArray.append([2,5,7])

In [5]: myArray
Out[5]: [[1, 2, 3], [1, 3, 5], [2, 5, 7]]

In [6]: myArray[2]
Out[6]: [2, 5, 7]

In [7]: myArray[1][1]
Out[7]: 3

inveratulo
May 14, 2002
wat

No Safe Word posted:

Depends on what you want to do. If you're going to be doing math-like stuff, save yourself a headache and just start with NumPy from the get-go:
http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html

Otherwise, you can just start with a list, insert/append a new list, and so on.
code:
In [1]: myArray = []

In [2]: myArray.append([1,2,3])

In [3]: myArray.append([1,3,5])

In [4]: myArray.append([2,5,7])

In [5]: myArray
Out[5]: [[1, 2, 3], [1, 3, 5], [2, 5, 7]]

In [6]: myArray[2]
Out[6]: [2, 5, 7]

In [7]: myArray[1][1]
Out[7]: 3

Thanks for the suggestion; as it always turns out, I find a solution shortly after posting for help on something. I think I am going to just use a dictionary with tuple addressing, like so:
code:
myDict = {}
myDict[0,0] = "welp"
myDict[0,1] = "rofl"
and so on...

SlightlyMadman
Jan 14, 2005

inveratulo posted:

Thanks for the suggestion; as it always turns out, I find a solution shortly after posting for help on something. I think I am going to just use a dictionary with tuple addressing, like so:
code:
myDict = {}
myDict[0,0] = "welp"
myDict[0,1] = "rofl"
and so on...

Oh wow, it never occurred to me that I could use tuples as dictionary keys, but it's so obvious that I feel sort of foolish.

Performance-wise, for a grid data structure, this would still be less efficient than a 2-dimensional array, right?

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

SlightlyMadman posted:

Oh wow, it never occurred to me that I could use tuples as dictionary keys, but it's so obvious that I feel sort of foolish.

Performance-wise, for a grid data structure, this would still be less efficient than a 2-dimensional array, right?

Depends on what you use it for. In a 2D array, looking up a cell (including iterating) and writing to a cell are both O(1) and about as fast as you can make it.

With a Python dict, looking up or altering a known key is also O(1) in the average case, although the worst case is O(n) (if there are lots of hash collisions). An array is still faster since the constant factor is lower, I believe, but that should only matter if you're using this in an extremely performance-critical loop.

If your array is dense (ie. you know that every integer in a given range is in the table) you can iterate through almost as fast as an array, by doing "for i in range (...): for j in range(...): val = d[i, j]". (This is O(n), but again the constant factor is higher than for an array.) If you iterate through with "for i, j in d: val = d[i, j]" instead, I believe the complexity is O(nlogn) (and it gets you the keys in arbitrary order - iterating in sorted order is even slower).

The tradeoff is that if your array is sparse (most keys don't have a value, or have the same default value) a dict will be much more space-efficient since it only stores the keys with a value. Iterating over every key with a value in the array version will take O(n) but you're guaranteed to have to go through the entire array and check whether each key is actually set; iterating in the dict version is O(nlogn), but the actual value of n is the number of keys which are set, not the total range of the array, so at some level of sparseness which I'm too lazy to calculate the dict version will become faster.

Aside, does anyone know a good site listing the complexity guarantees of common operations for common data types? I should know this off by heart but I always end up having to look it up...

JoeNotCharles fucked around with this message at 17:20 on Oct 29, 2008

No Safe Word
Feb 26, 2005

JoeNotCharles posted:

Aside, does anyone know a good site listing the complexity guarantees of common operations for common data types? I should know this off by heart but I always end up having to look it up...
Something like the table on these pages:

http://www.cplusplus.com/reference/stl/

(which are the STL container operations' complexities)

for Python would be awesome.

king_kilr
May 25, 2007

No Safe Word posted:

Something like the table on these pages:

http://www.cplusplus.com/reference/stl/

(which are the STL container operations' complexities)

for Python would be awesome.

http://wiki.python.org/moin/TimeComplexity

Tada :)

Tomed2000
Jun 24, 2002

Has anyone ever set up Emacs to work with Python in Vista64? I've installed Python to the default C:\Python26 and Emacs is currently residing in C:\Emacs. Python mode works fine when opening .py files but whenever I try to start the interpreter I get this error:

quote:

apply: Searching for program: no such file or directory, python

I've been trying to find a fix for this for the past hour and I can't figure out what the hell is going on.

tef
May 30, 2004

-> some l-system crap ->
Add c:\python26 to the environment variable PATH ?

Tomed2000
Jun 24, 2002

tef posted:

Add c:\python26 to the environment variable PATH ?
If this is what you mean:


then I already did it, in both local variables and environment variables just to be sure. Maybe I should move this to tech support subforum.

TOO SCSI FOR MY CAT
Oct 12, 2008

this is what happens when you take UI design away from engineers and give it to a bunch of hipster art student "designers"

Tomed2000 posted:

If this is what you mean:


then I already did it, in both local variables and environment variables just to be sure. Maybe I should move this to tech support subforum.

No, find the "PATH" (not "PYTHONPATH") variable and append ";C:\Python26" to the end of it.

Tomed2000
Jun 24, 2002

Janin posted:

No, find the "PATH" (not "PYTHONPATH") variable and append ";C:\Python26" to the end of it.

Oh, found it. Thanks.

king_kilr
May 25, 2007
Mr. Noller(forgot your SA name), your proposals for pycon sound very cool, I'd attend both of them.(As long as they don't interfere with mine of coure :P )

m0nk3yz
Mar 13, 2002

Behold the power of cheese!

king_kilr posted:

Mr. Noller(forgot your SA name), your proposals for pycon sound very cool, I'd attend both of them.(As long as they don't interfere with mine of coure :P )

I proposed one on MultiProcessing, and one on Concurrency/Distributed systems. Dunno if they'll get approved.

Oh, and someone else proposed a HPC talk too, but it's tagged with IronPython too

m0nk3yz fucked around with this message at 18:49 on Oct 31, 2008

king_kilr
May 25, 2007

m0nk3yz posted:

I proposed one on MultiProcessing, and one on Concurrency/Distributed systems. Dunno if they'll get approved.

Hehe, I can see votes on other people's proposals(but not mine own), not sure if I'm allowed/supposed to say anything. But I wouldn't worry about he MultiProcessing one :P

The CRAIGGERS
Mar 3, 2006
I am foo incarnate!
A friend and I are both new to Python. Both of us are C nerds with a smattering of other languages under our belts. Both of us are having some problems in the same area: references and scope. Coming from C backgrounds we're totally at a loss about how to do some seemingly basic stuff.

I know by now that Python only passes by value. I've given up finding a way to pass by reference and now I just want to know what I don't understand. My guess is this comes up so often as to make Python people retch, but I'm sure my lack of understanding is simply because we don't yet "get" Python. Just like how I had to "get" perl or oop, I have the distinct impression that something just isn't clicking with me in Python.

How did you deal with this? I've seen examples of people creating empty lists or something to pass into functions to force them to be a pass-by-reference, but this seems exceedingly klugy to me and makes me think I'm just trying to shoehorn things into the language.

We're also having problems with scope between modules. For example, a function in a module trying to grab global variables from the calling script isn't as easy as I think it should be. We had the thought of passing a dict with everything we want in it but that also screams of wrongness.

Am I using the wrong language or am I just using the language wrong? (My that was a clever ending for a post.)

Adbot
ADBOT LOVES YOU

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

The CRAIGGERS posted:

I know by now that Python only passes by value. I've given up finding a way to pass by reference and now I just want to know what I don't understand. My guess is this comes up so often as to make Python people retch, but I'm sure my lack of understanding is simply because we don't yet "get" Python. Just like how I had to "get" perl or oop, I have the distinct impression that something just isn't clicking with me in Python.

How did you deal with this? I've seen examples of people creating empty lists or something to pass into functions to force them to be a pass-by-reference, but this seems exceedingly klugy to me and makes me think I'm just trying to shoehorn things into the language.

Python can easily return multiple values at once by returning a list or tuple. Instead of doing "int x = 10, y = 20, z = 30; ...; updateCoords(x, y, z);" do "(x, y, z) = (10, 20, 30); ...; (x, y, z) = updateCoords(x, y, z)".

The CRAIGGERS posted:

We're also having problems with scope between modules. For example, a function in a module trying to grab global variables from the calling script isn't as easy as I think it should be. We had the thought of passing a dict with everything we want in it but that also screams of wrongness.

Why would or should a module be able to access variables from it's caller? If you're going to kill reusability like that, why bother putting things in a separate module at all?

Passing all the data the module needs down to it somehow is exactly what you want to do, and a dict is a fine way to do that.

  • Locked thread