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
Lysidas
Jul 26, 2002

John Diefenbaker is a madman who thinks he's John Diefenbaker.
Pillbug
No, one can define functions that take keyword-only arguments like so:

Python code:
def func(arg1, arg2, *, kwarg=None):
    print(arg1, arg2, kwarg)
code:
>>> func(1, 2)
1 2 None
>>> func(1, 2, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() takes 2 positional arguments but 3 were given
>>> func(1, 2, kwarg=5)
1 2 5
You can even leave off the default value, which has the odd but consistent behavior of making a keyword argument required:
code:
>>> def func(arg1, arg2, *, kwarg):
...   pass
... 
>>> func(1, 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() missing 1 required keyword-only argument: 'kwarg'

Adbot
ADBOT LOVES YOU

tef
May 30, 2004

-> some l-system crap ->
Maybe they're using a five year old python due to some legacy constraints?

Stringent
Dec 22, 2004


image text goes here

BigRedDot posted:

Edit: FWIW I think this is probably a common confusion, given that the spelling of default arguments in function definitions is basically the same as the spelling of passing keyword arguments in function invocations. But they are two separate, different things.

Yeah, I get that now, but it was a bit of an unpleasant surprise. I think I'd rather not be able to assign defaults to positional arguments than to implicitly switch between the two.

And yeah, we're past due to move things over to 3, but it's a large code base for the number people working on it.

Cingulate
Oct 23, 2012

by Fluffdaddy

BigRedDot posted:

Edit: FWIW I think this is probably a common confusion, given that the spelling of default arguments in function definitions is basically the same as the spelling of passing keyword arguments in function invocations. But they are two separate, different things.
What the I never even knew this

hooah
Feb 6, 2006
WTF?
I don't understand what BigRedDot is saying. Does spelling mean something that different in this context than in everyday English?

Dominoes
Sep 20, 2007

hooah posted:

I don't understand what BigRedDot is saying. Does spelling mean something that different in this context than in everyday English?
yep; 'spelling' refers to syntax in this case.

The March Hare
Oct 15, 2006

Je rêve d'un
Wayne's World 3
Buglord
I'm doing the Coursera Algorithms 1 class in order to (hopefully) get myself a bit more comfortable in interviews, and also because I think it is probably worth doing. That said, the course is in Java, which I don't know or really care to learn, so I'm doing it in Python instead. Because of this, however, I don't really have a feedback option for my implementation of the homework stuff. If any of you guys have some free time, I'd appreciate some crits.

I've got my solution for the week 1 assignment (Monte Carlo w/ weighted quick union w/ path compression) up here https://github.com/LarryBrid/algos and the assignment spec is here http://coursera.cs.princeton.edu/algs4/assignments/percolation.html

I had a couple of pain points. The implementation of quick union uses one dimensional arrays mapping index to nodes and the value at that index to the root of that node. So, [0, 1, 0] would be node 0 as the parent of node 2 and then node 1 as its own parent in its own tree.

This is fine, but their spec has us using 2d coordinates for the percolation bit so that we can check cardinal neighbors. Maybe there is an easy way to do this, but I ended up having to write some code to constantly convert from node -> x, y pair and back. It wasn't ever a real problem, it just felt kind of lovely.

The second one was in the implementation of the Percolation class, I ended up breaking the somewhat complicated process of checking cardinal neighbors into its own function outside of the class, called open_and_union. This also felt like maybe it should just be part of the class, but I wasn't really sure.

(Also, I usually go pretty ham w/ commenting my code but I've been filling a paper notebook for all of this stuff, so that is somewhat lacking in these implementations. If it's unreadable garbage I can go back and add it in, and I'll probably make a point of doing it for future assignments now that I realize that is probably going to be a problem.)

tef
May 30, 2004

-> some l-system crap ->
The code looks reasonably ok for the interface you've been given. i'd probaby do a few things differently.

Take a Grid class, which has open, is_open, close, is_close, open_random, and neighbours methods, handling the virtual top and bottom row.

The percolator would take a Grid, along with your DisjointSet (QuickUnion), and expose __init__, step() and percolates methods. The step method would be a cleaned up version of open_and_union.

code:
p = self.grid.open_random()
for n in self.grid.neighbours(p): 
    if self.grid.is_open(n):
        self.disjoint_set.union(n, p)
Then i'd have a simulator function that returned a stats object

code:
def simulate(percolator, times):
    s = Stats()
    for n in range(times):
        p = percolator()
        while not p.percolated():
            p.step()
        s.add_sample(p.steps)
    return s

tef fucked around with this message at 03:55 on Aug 31, 2015

BigRedDot
Mar 6, 2008

Lysidas posted:

No, one can define functions that take keyword-only arguments like so:
Sure, in python 3. I work on a library that has to work on both python 2 and 3 so I don't get to use lots of fun things.

quote:

Maybe they're using a five year old python due to some legacy constraints?
Just because python 3 can define funcs with kwarg only arguments, does not mean every function does.

Emacs Headroom
Aug 2, 2003

Thermopyle posted:

When you're using a library that provides objects whose data is provided by an online bank for personal checking/savings which of the following designs is most appealing to you?
...

I'm late to this opinion poll, but I would not use properties, since the idiom I use for properties is that they're meant to be free, instant look-ups. Using properties (or getters) with caching could make sense, but you have the invalidation problem (as in, can you guarantee that you're not going to be returning invalid data with a timeout that's still useful?). I would probably default to getters with no caching.

Gothmog1065
May 14, 2009
Code Optimization time!

Doing codingame, and on the last "easy" project. What I have works, but it's too slow. I know there is a faster way to do this, but I'm not sure how, it's probably some basic programming thing I'm missing.

Python code:
N = int(input())
list = []
smallest = -1

for i in range(N):
	Pi = int(input())
	list.append(Pi)

for i in range(N):
	num1 = list[i]
	for j in range(N):
		num2 = list[j]
		diff = abs(num1-num2)
		if j != i and (diff < smallest or smallest < 0):
			smallest = diff 

print(smallest)
The first for builds the list I'm using (I was using two), and the second for does the comparison of each number on the list. The list may not be in order. I'm thinking of somehow dropping off already done comparisons, but not sure the best way to handle that. Guide me goons!

DarthRoblox
Nov 25, 2007
*rolls ankle* *gains 15lbs* *apologizes to TFLC* *rolls ankle*...
Ok, so first off you need to change up your variable names - using list as a variable name is a really bad idea, since you just overwrote the built-in list function. It's not causing problems here, but will bite you in the rear end at some point if you don't get out of the habit.

Pi is also a pretty bad name - I know it's how the game refers to the speed, but I'd use something like "horse_speed" since I won't forget what horse_speed means, but I will forget what Pi means.

On to the actual problem. Right now, you're comparing every horse with ever other horse including itself. That's not an issue when your number of horses is small, but as you keep adding horses you're adding exponentially more comparisons. Think about it - do you really need to compare every horse with every other horse? Like you said, the list isn't guaranteed to be in order, but could you do anything to change that? From there, if the list is known to be ordered how could you reduce the number of comparisons that you have to do for any given horse?

edit: Also, look into list comprehensions instead of for loops - they'll help make your code much more readable.

DarthRoblox fucked around with this message at 22:26 on Sep 2, 2015

Gothmog1065
May 14, 2009

Viking_Helmet posted:

Ok, so first off you need to change up your variable names - using list as a variable name is a really bad idea, since you just overwrote the built-in list function. It's not causing problems here, but will bite you in the rear end at some point if you don't get out of the habit.

Pi is also a pretty bad name - I know it's how the game refers to the speed, but I'd use something like "horse_speed" since I won't forget what horse_speed means, but I will forget what Pi means.

On to the actual problem. Right now, you're comparing every horse with ever other horse including itself. That's not an issue when your number of horses is small, but as you keep adding horses you're adding exponentially more comparisons. Think about it - do you really need to compare every horse with every other horse? Like you said, the list isn't guaranteed to be in order, but could you do anything to change that? From there, if the list is known to be ordered how could you reduce the number of comparisons that you have to do for any given horse?

edit: Also, look into list comprehensions instead of for loops - they'll help make your code much more readable.

Yeah, the stupid list variable names were from when I had two lists. (List_1 and list_2, i changed it in a hurry). I generally leave the set variable names along as they are noted in the game code. Otherwise, I'll be able to poke them when I'm back at work tomorrow, but let me know if I"m on the right track:

Python code:
for i in range(N):
    num1 = horses[i]
    for j in range(i+1,N):
        num2 = horses[j]
        diff = abs(num1-num2)
        if diff < smallest or smallest < 0:
            smallest = diff

Fergus Mac Roich
Nov 5, 2008

Soiled Meat
So you're finding the smallest difference between any two values in the list, right? As viking_helmet was getting at, your algorithm needs to minimize the number of times it needs to "touch" its elements. Now, your new solution is better than your old one, but step back from it and think: what if you could just know where the num2 value that's most similar to num1 is in the list? There's actually a way to do it, and it's right under your nose. I'll just stick the answer in spoiler tags, because I know I didn't find the fact that this method is faster to be intuitive at first, but you might be smarter than me so make sure to think about it for a bit before looking.

So if your original algorithm takes time equivalent to N^2, most practical sorting algorithms are closer to N * log N, which is way, way faster for a large N. So much faster that you can just call the list's sort() method, THEN loop through the entire list, checking each value against only the next value in the list. Be careful you don't run off the end of the list.

Proteus Jones
Feb 28, 2013



Fergus Mac Roich posted:

So you're finding the smallest difference between any two values in the list, right? As viking_helmet was getting at, your algorithm needs to minimize the number of times it needs to "touch" its elements. Now, your new solution is better than your old one, but step back from it and think: what if you could just know where the num2 value that's most similar to num1 is in the list? There's actually a way to do it, and it's right under your nose. I'll just stick the answer in spoiler tags, because I know I didn't find the fact that this method is faster to be intuitive at first, but you might be smarter than me so make sure to think about it for a bit before looking.

So if your original algorithm takes time equivalent to N^2, most practical sorting algorithms are closer to N * log N, which is way, way faster for a large N. So much faster that you can just call the list's sort() method, THEN loop through the entire list, checking each value against only the next value in the list. Be careful you don't run off the end of the list.

I think this is probably a good place to say, you can always check out what you have at your disposal in the objects you're using. Do that in the console using dir(object).

So for list type you would do dir(list) and see that sort is one of the list methods. help(list.sort) will pull up the docstring

KICK BAMA KICK
Mar 2, 2009

If you want to learn more about this kind of thing, I took a good Coursera class over the last few months, Introduction to Algorithmic Thinking from Rice University. That will explain some of the stuff you're looking at in this discussion, like why Fergus's suggestion of sorting the list runs in N log N (and what that even means). Check that out; it's not super time consuming or rigorous (we had two weeks for each set of lectures and problems) but the lectures really are great. All the coding is done in Python.

Gothmog1065
May 14, 2009
Thanks guys! I was overthinking it pretty badly, and after reading flosofl and fergus's hints (I had to cheat), I figured it out pretty drat easily after that. Ended up with this, though I"m sure there's always the way to make it even better (I could probably write it into the first for loop thinking about it just reversing the math signs a bit to save even more time), but this finally got it to work:

Python code:
horses.sort()
for i in range(N):
	if i != N-1:
		diff = abs(horses[i] - horses[i+1])
		if diff < smallest or smallest < 0:
			smallest = diff

KICK BAMA KICK posted:

If you want to learn more about this kind of thing, I took a good Coursera class over the last few months, Introduction to Algorithmic Thinking from Rice University. That will explain some of the stuff you're looking at in this discussion, like why Fergus's suggestion of sorting the list runs in N log N (and what that even means). Check that out; it's not super time consuming or rigorous (we had two weeks for each set of lectures and problems) but the lectures really are great. All the coding is done in Python.

I will look into that because I'm loving terrible at word problems and math, always have been.

This means I've done all the "basic" stuff at codingame except for the skynet one, which I can't wrap my loving head around for some reason, but that's a different problem for a different day.

Gothmog1065 fucked around with this message at 02:01 on Sep 3, 2015

Proteus Jones
Feb 28, 2013



Gothmog1065 posted:

Thanks guys! I was overthinking it pretty badly, and after reading flosofl and fergus's hints (I had to cheat), I figured it out pretty drat easily after that. Ended up with this, though I"m sure there's always the way to make it even better (I could probably write it into the first for loop thinking about it just reversing the math signs a bit to save even more time), but this finally got it to work:

Python code:
horses.sort()
for i in range(N):
	if i != N-1:
		diff = abs(horses[i] - horses[i+1])
		if diff < smallest or smallest < 0:
			smallest = diff
I will look into that because I'm loving terrible at word problems and math, always have been.

This means I've done all the "basic" stuff at codingame except for the skynet one, which I can't wrap my loving head around for some reason, but that's a different problem for a different day.

This is more of a style thing, but I hate having more conditionals than I really need. I'd probably redo it like this.
Python code:
horses.sort()
for i in range(len(horses) - 1):
	diff = horses[i+1] - horses[i]  # it's sorted in ascending order, why do more work than you need to?
	if diff < smallest or smallest < 0:
		smallest = diff

Proteus Jones fucked around with this message at 02:14 on Sep 3, 2015

SurgicalOntologist
Jun 17, 2004

...and it might be marginally faster using generators, with less indexing.

Python code:
horses.sort()
smallest_diff = min(second - first for first, second in zip(horses, horses[1:]))
and izip if it's python 2, I think.

Fergus Mac Roich
Nov 5, 2008

Soiled Meat

SurgicalOntologist posted:

...and it might be marginally faster using generators, with less indexing.

Python code:
horses.sort()
smallest_diff = min(second - first for first, second in zip(horses, horses[1:]))
and izip if it's python 2, I think.

Python is cool as poo poo.

KICK BAMA KICK
Mar 2, 2009

poo poo, that is something that comes up a lot and I never once thought of zipping a list against an offset portion of itself. Very cool.

Ashex
Jun 25, 2007

These pipes are cleeeean!!!
Edit Never mind, I just grinded through the docs and figured it out.

Ashex fucked around with this message at 17:05 on Sep 3, 2015

Fergus Mac Roich
Nov 5, 2008

Soiled Meat
So, Python mavens, is this the most elegant way to do this?

code:
def countit(arg):
    count_sub1, count_sub2 = Counter(), Counter()
    with open(arg) as dataf:
        thing = DictReader(dataf, fieldnames=fieldnames)
	for item in thing:
	    if validate(item, is_sub1_appropriate):
	        count_sub1 += 1
	    elif validate(item, is_sub2_appropriate):
		count_sub2 += 1 
    return count_sub1, count_sub2
fieldnames is a list of strings that comes from outside the function. validate looks a bit like this, in case it's not clear what I'm doing:

code:
def validate(item, func):
    item = {key: item[key].strip() for key in item} #maybe some things have whitespace; the functions called below do string comparisons
    return meets_common_criteria(item) and func(item)
For some reason it feels like I could improve this, but I just can't get my head around how. (The variable names are made up)

edit: Well, right after posting this I figured out the obvious way I was overthinking it. The code now reflects the change I made, but if anyone has any magic suggestions, I'd love to hear 'em.

Fergus Mac Roich fucked around with this message at 00:30 on Sep 4, 2015

chutwig
May 28, 2001

BURLAP SATCHEL OF CRACKERJACKS

Fergus Mac Roich posted:

So, Python mavens, is this the most elegant way to do this?

code:
def countit(arg):
    count_sub1, count_sub2 = Counter(), Counter()
    with open(arg) as dataf:
        sub1, sub2 = tee(DictReader(dataf, fieldnames=fieldnames))
        sub1 = filter(partial(validate, func=is_sub1), sub1)
        sub2 = filter(partial(validate, func=is_sub2), sub2)
        for item in sub1:
            count_sub1[item[a_key_from_fieldnames]] += 1
        for item in sub2:
            count_sub2[item[a_key_from_fieldnames]] += 1
    return count_sub1, count_sub2
fieldnames is a list of strings that comes from outside the function. validate looks a bit like this, in case it's not clear what I'm doing:

code:
def validate(item, func):
    item = {key: item[key].strip() for key in item}
 #maybe some things have whitespace; the functions called below do string comparisons
    return meets_common_criteria(item) and func(item)
For some reason it feels like I could improve this, but I just can't get my head around how. (The variable names are made up)

It seems like you wrote countit() the way you did so that you could use tee() to not read the file twice, but with the consequence that now everything else in the function is doubled up. If you expect to re-use the file contents over and over, read it into a buffer outside the function and pass that in. There are also some things being accessed inside countit() that look like globals, e.g., fieldnames.

Do the counts need to be done together like that? Is there a reason why they can't be done one at a time? If the state of one counter has no bearing on the other, then I would advise doing them separately instead of doubling up. Generally speaking you will want to deal with having 0 things, 1 thing, or more than 1 thing. Right now you're dealing with 2 things as 2 things, instead of dealing with them as 1 thing twice. Changing countit() to handle one counter as a time is a more generalizable solution.

Emacs Headroom
Aug 2, 2003

SurgicalOntologist posted:

...and it might be marginally faster using generators, with less indexing.

Python code:
horses.sort()
smallest_diff = min(second - first for first, second in zip(horses, horses[1:]))
and izip if it's python 2, I think.

Generators are very quick! I thought numpy would trounce them, but not for this problem.

code:
In [31]: horses = np.random.randint(0, 3e12, 100000).tolist()

In [32]: %timeit np.min(np.diff(np.array(sorted(horses))))
10 loops, best of 3: 77.6 ms per loop

In [33]: %timeit h2 = sorted(horses); smallest_diff = min(second - first for first, second in zip(h2, h2[1:]))
1 loops, best of 3: 134 ms per loop

Fergus Mac Roich
Nov 5, 2008

Soiled Meat

chutwig posted:

It seems like you wrote countit() the way you did so that you could use tee() to not read the file twice, but with the consequence that now everything else in the function is doubled up. If you expect to re-use the file contents over and over, read it into a buffer outside the function and pass that in. There are also some things being accessed inside countit() that look like globals, e.g., fieldnames.

Do the counts need to be done together like that? Is there a reason why they can't be done one at a time? If the state of one counter has no bearing on the other, then I would advise doing them separately instead of doubling up. Generally speaking you will want to deal with having 0 things, 1 thing, or more than 1 thing. Right now you're dealing with 2 things as 2 things, instead of dealing with them as 1 thing twice. Changing countit() to handle one counter as a time is a more generalizable solution.

What do you think of this?

Python code:
#calling code
fieldnames = #some strings
mykey = #a key from fieldnames
with open(myfile) as f:
    mydata = list(DictReader(f, fieldnames=fieldnames))
sub1 = countit(*mydata, validator=partial(validate, func=is_sub1), key=mykey)
sub2 = countit(*mydata, validator=partial(validate, func=is_sub2), key=mykey)

def countit(*args, validator, key):
    count = Counter()
    items = [item for item in args if validator(item)]
    for item in items:
        count[item[key]] += 1
    return count
This script actually does have some globals that are never modified, and yeah, that includes fieldnames. I've deemed it "okay" for this since it's just a script that runs for a second, writes all the counts to a file, and dies. However, I understand that you're right that as far as elegance and best practices, globals are generally bad design.

Fergus Mac Roich fucked around with this message at 01:37 on Sep 4, 2015

chutwig
May 28, 2001

BURLAP SATCHEL OF CRACKERJACKS

Fergus Mac Roich posted:

What do you think of this?

Python code:
#calling code
fieldnames = #some strings
mykey = #a key from fieldnames
with open(myfile) as f:
    mydata = list(DictReader(f, fieldnames=fieldnames))
sub1 = countit(*mydata, validator=partial(validate, is_sub1), key=mykey)
sub2 = countit(*mydata, validator=partial(validate, is_sub2), key=mykey)

def countit(*args, validator, key):
    count = Counter()
    items = [item for item in args if validator(item)]
    for item in items:
        count[item[key]] += 1
This script actually does have some globals that are never modified, and yeah, that includes fieldnames. I've deemed it "okay" for this since it's just a script that runs for a second, writes all the counts to a file, and dies. However, I understand that you're right that as far as elegance and best practices, globals are generally bad design.

I think that is a lot more reasonable, yeah. Obviously there's such a thing as quick hacky scripts, but I've been burned by wackity global variable scope too much in the past and prefer to pass arguments around explicitly.

Nippashish
Nov 2, 2005

Let me see you dance!

Emacs Headroom posted:

Generators are very quick! I thought numpy would trounce them, but not for this problem.

Of course they're going to be comparable if you do the slow part with python objects both times, if do the whole thing in numpy its much faster:

code:
In [10]: horses = np.random.randint(0, 3e12, 100000)

In [11]: %timeit np.min(np.diff(np.sort(horses)))
100 loops, best of 3: 6.74 ms per loop

In [12]: horses = np.random.randint(0, 3e12, 100000).tolist()

In [13]: %timeit h2 = sorted(horses); smallest_diff = min(second - first for first, second in zip(h2, h2[1:]))
10 loops, best of 3: 79.9 ms per loop

Emacs Headroom
Aug 2, 2003

Nippashish posted:

Of course they're going to be comparable if you do the slow part with python objects both times, if do the whole thing in numpy its much faster:

Sure, but I deliberately just wanted to test the "finding the min of the sorted list" part, not sorting a python list vs. sorting a numpy array.

Fergus Mac Roich
Nov 5, 2008

Soiled Meat

chutwig posted:

I think that is a lot more reasonable, yeah. Obviously there's such a thing as quick hacky scripts, but I've been burned by wackity global variable scope too much in the past and prefer to pass arguments around explicitly.

Cool, thanks. I'll take your advice about globals, too. For once I'll do the smart thing and learn from others' experience. :)

QuarkJets
Sep 8, 2008

Emacs Headroom posted:

Sure, but I deliberately just wanted to test the "finding the min of the sorted list" part, not sorting a python list vs. sorting a numpy array.

You kept rewriting the list to a new numpy array in the numpy example, though. That's a lot of extra memory management that your generator example doesn't have.

The real test would be to create a sorted numpy array and then convert that array into a list, and then run timeit and just the "finding the min of the sorted list" part

e:
Python code:
>>> horses_array = np.sort(np.random.randint(0, 3e6, 100000))
>>> horses_list = horses_array.tolist()
>>> print timeit('np.min(np.diff(horses_array))', 
	setup='import numpy as np; from __main__ import horses_array', 
	number=1000), 'ms per loop'
0.691206947133 ms per loop
>>> print timeit('min(second - first for first, second in zip(horses_list, horses_list[1:]))', 
	setup='import numpy as np; from __main__ import horses_list', 
	number=1000), 'ms per loop'
56.1057794698 ms per loop
This code doesn't test differences in sorting algorithms, it only tests difference in time that it takes to find the min of the pre-sorted list/array. Numpy is roughly 80 times faster at doing that.

If I import the list and convert it to an array then the performance difference is mostly killed:

Python code:
>>> print timeit('np.min(np.diff(np.array(horses_list)))', 
	setup='import numpy as np; from __main__ import horses_list', 
	number=1000), 'ms per loop'

33.7019170816 ms per loop

QuarkJets fucked around with this message at 05:44 on Sep 4, 2015

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



SurgicalOntologist posted:

...and it might be marginally faster using generators, with less indexing.

Python code:
horses.sort()
smallest_diff = min(second - first for first, second in zip(horses, horses[1:]))
and izip if it's python 2, I think.

Wouldn't you want to use islice instead of regular slicing for a throwaway list or is the interpreter somehow smart enough to not make a new list object in that case?

(yes I understand the underlying values aren't copied, but the list object would be and I don't see any reason to copy the object when it's just going to be iterated once and thrown away)

Hughmoris
Apr 21, 2007
Let's go to the abyss!
Any recommended resources for learning OO programming, in Python 3? I've been getting by using basic flow control and conditional statements, and I feel like my development has stalled.

Hughmoris fucked around with this message at 23:33 on Sep 5, 2015

Proteus Jones
Feb 28, 2013



Hughmoris posted:

Any recommended resources for learning OO programming, in Python 3? I've been getting by using basic flow control and conditional statements, and I feel like my development has stalled.

If you're willing to spend money, I like Team Treehouse. ($25/mo. or $199/yr) You get access to all the training, so not just Python.

Even though I considered myself "intermediate" with the automation I'd do I thought I'd give it a spin for the Data Science course they had. Turns out my poo poo worked out sheer stubbornness. I was a monkey banging the ground with a wrench. I ended up doing their whole Learn Python and I definitely learned I had Been Doing It Wrong. In fact it made crystal clear subjects that had confused and frightened me before like Classes, Methods and Inheritance (I typically wrote brute-force, bulldozer code before).

I'm in a much better place programming wise and more confident with my knowledge. In fact with the solid foundation, I find it much easier get up to speed on newer topics.

I definitely wouldn't call them advanced courses or really applicable to someone with a really solid mastery in Python, but they're definitely good for the beginning to intermediate programmer.

Be aware it is Python 3 they use.

I'm a fan and I'm going to be starting the Swift track when I wrap up a project I'm eyeball deep in at work.

Dominoes
Sep 20, 2007

Looking for some wisdom on when you'd use Flask vs Django. Rule of thumb I've read: Flask for small projects, Django for big ones.

I learned Django a while back, and recently set up a project with Flask, which I'm learning as I'm going. The initial setup of Flask, to render custom HTML, was cleaner than Django. Less boilerplate, easier config, cleaner directory structure etc. The url routing system was easier. Now that I'm adding things like a database, admin page, and logins/authentication, my Flask project's becoming messier. The code's still clean, but I need to reference multiple documentation sites (ie one for each extension). Database migrations are clumsy compared to Django's workflow. Some extensions require workarounds to play with other extensions, ie security and admin. Many import statements.

Dominoes fucked around with this message at 01:22 on Sep 7, 2015

Hughmoris
Apr 21, 2007
Let's go to the abyss!

flosofl posted:

If you're willing to spend money, I like Team Treehouse. ($25/mo. or $199/yr) You get access to all the training, so not just Python.

Even though I considered myself "intermediate" with the automation I'd do I thought I'd give it a spin for the Data Science course they had. Turns out my poo poo worked out sheer stubbornness. I was a monkey banging the ground with a wrench. I ended up doing their whole Learn Python and I definitely learned I had Been Doing It Wrong. In fact it made crystal clear subjects that had confused and frightened me before like Classes, Methods and Inheritance (I typically wrote brute-force, bulldozer code before).

I'm in a much better place programming wise and more confident with my knowledge. In fact with the solid foundation, I find it much easier get up to speed on newer topics.

I definitely wouldn't call them advanced courses or really applicable to someone with a really solid mastery in Python, but they're definitely good for the beginning to intermediate programmer.

Be aware it is Python 3 they use.

I'm a fan and I'm going to be starting the Swift track when I wrap up a project I'm eyeball deep in at work.

Thanks for the info. I don't mind paying money, if I get my money's worth. I'll look into Team Treehouse. Also, I think I'm in the same boat as you. I've wrote some automation scripts for work but they are ill-designed and use brute force to accomplish their task. Heaven help who ever comes in behind me and wants to tweak what I've wrote, because its a mess.

Emacs Headroom
Aug 2, 2003

Dominoes posted:

Looking for some wisdom on when you'd use Flask vs Django. Rule of thumb I've read: Flask for small projects, Django for big ones.

I'm not an expert here, but my meagre experience is that Django is a big framework which just happens to be in Python. I'd use Django when you want a big framework (including stuff like admin, db handling, etc), and you like Django's framework (it's a version of MVC), and you like the idea of your site being written in Python (less common these days than the js frameworks like Angular, React, Ember, whatever-the-gently caress-is-new-this-week, etc).

Flask as you mention is good for small things, but I'd refine that by saying that Flask is especially good at things that don't require a lot of moving parts -- stuff like a REST API, or some straightforward web pages. If you have more moving parts (talking to databases, having admin pages and views, etc), then Flask might feel a little underpowered.

chutwig
May 28, 2001

BURLAP SATCHEL OF CRACKERJACKS

Emacs Headroom posted:

Flask might feel a little underpowered.

Flask intentionally deals with a much smaller subset of the problem domain than Django does. As you said, Django is a large framework, and it provides a lot of different things that Flask by design does not. You can do anything in Flask that you can do in Django, but you'll need to do a lot more of your own plumbing. Some people prefer it that way. I've published Real Applications™ in Django and tinkered with Flask, and I like the lightweight feeling of Flask. Django's out-of-the-box admin site is still one of its huge selling points, though, and Flask won't ever provide that.

Also, to your point about Angular/React/Ember stuff, there's no reason why you can't have the frontend of your site written using one of those while the backend is Django/Flask/Rails/something else that emits JSON to the frontend framework. It's not really about the site itself being written "in Python", since that's all on the backend and you're not going to be able to do anything dynamic without JS.

Emacs Headroom
Aug 2, 2003

chutwig posted:

Also, to your point about Angular/React/Ember stuff, there's no reason why you can't have the frontend of your site written using one of those while the backend is Django/Flask/Rails/something else that emits JSON to the frontend framework.

Yeah I agree, but like I said if you're putting up a REST API, then Flask will probably be a more natural fit (unless you're at a RealApplication (tm) scale, in which case you start mucking with Tornado/Twisted/whatever, or give up and start making your backend in a jvm stack). I'd also probably assume that Dominoes isn't asking us this stuff because he's planning his service-oriented architecture though...

Adbot
ADBOT LOVES YOU

Dominoes
Sep 20, 2007

Thanks dudes! I'm asking because I set up a simple website to help out at work, that only consists of a set of links and a roster of names/contact info. To view the roster, you need to be logged in to a verified account, and a few people will be able to edit the roster and links. This seemed like Flask territory, but the db, admin and auth system are already taking away some of the simplicity.

Dominoes fucked around with this message at 12:01 on Sep 7, 2015

  • Locked thread