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
KICK BAMA KICK
Mar 2, 2009

Just spent enough time fighting with matplotlib in a Python 2 virtualenv on Windows that I gave up and rebooted into an Ubuntu livestick. Then ran into problems there cause I forgot how much PyCharm was doing behind the scenes to make it easy to just run a script from wherever with relative imports and not worry about the path and such.

So it sounds like time to try Anaconda in Windows. Does it have like virtualenvs of its own or do I put it inside a virtualenv and how does it integrate with PyCharm?

Adbot
ADBOT LOVES YOU

Thermopyle
Jul 1, 2003

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

KICK BAMA KICK posted:

Just spent enough time fighting with matplotlib in a Python 2 virtualenv on Windows that I gave up and rebooted into an Ubuntu livestick. Then ran into problems there cause I forgot how much PyCharm was doing behind the scenes to make it easy to just run a script from wherever with relative imports and not worry about the path and such.

So it sounds like time to try Anaconda in Windows. Does it have like virtualenvs of its own or do I put it inside a virtualenv and how does it integrate with PyCharm?

It replaces the need for virtualenv.

You just point your project interpreter in PyCharm to your conda environment.

Nippashish
Nov 2, 2005

Let me see you dance!

Thermopyle posted:

It replaces the need for virtualenv.

It replaces virtualenv with conda.

accipter
Sep 12, 2003

pmchem posted:

Anaconda is also great for enterprise environments where getting Anaconda approved is one piece of paperwork, and you can't run "pip install" etc., because instead you're supposed to do more paperwork for each module.

This is the very reason that I use Anaconda at work.

Emacs Headroom
Aug 2, 2003

KICK BAMA KICK posted:

Just spent enough time fighting with matplotlib in a Python 2 virtualenv on Windows...

Couple of things not really Anaconda-related:

(1) PyCharm also runs in Ubuntu; it sounds like you were relying on PyCharm in Windows but not in Ubuntu?
(2) You shouldn't be worrying about the path after activation if you have your virtualenvs set up correctly; you just (in bash) do the '$ source ~/path/to/virtualenv/bin/activate' then launch python / ipython / whatever. I believe the relative imports will also allow you to call python binaries inside the virtualenv if you don't want to run the activation script for some reason
(3) A possibly even better solution for you if you're doing data analysis type stuff would be to run ipython notebook in your Ubuntu virtual machine. Then you can just (in windows) tunnel to it on the web port it uses (I think 8888), and you can do all the data analysis or prototyping you want there. Or still use the browser in Ubuntu, whatever you want

KICK BAMA KICK
Mar 2, 2009

Context is this is just for a Coursera algorithms class. Right, I wasn't using PyCharm in Ubuntu; I was trying to just boot it up, sudo apt-get install python-matplotlib and run what I thought was a simple program to generate the plots I needed. Error I got in Ubuntu was about "attempting a relative import not inside a package", which I'm not sure the cause of. __init__.py was in all the right places; the import was a simple from .sibling_module_in_the_same_directory import name, and it works fine in PyCharm so I assumed PyCharm was setting up something in the PYTHONPATH that made this OK. Might be a 2 vs. 3 thing cause I'm used to 3 but using 2 for the class, and I vaguely remember there being a difference between the two with regard to imports.

The issues I had getting matplotlib going in Windows were some of the well-known vcvarsall.bat things, which you can sidestep by using the Windows binary packages from the one web site everyone knows; after that when calling pyplot.whatever() it throws some errors about not finding some graphics library it needs, which a search indicates is a known issue with the paths it searches when run inside a virtualenv that can be fixed but gently caress it.

I ended up just c/ping all the (short) code into the same file to make it work under Ubuntu (just a one-off and the code isn't what you're turning in),. Then back in Windows I tried Anaconda and everything's perfect. (Actually Miniconda and then conda install matplotlib, not seeing any poo poo about vcvarsall.bat is like magic).

PongAtari
May 9, 2003
Hurry, hurry, hurry, try my rice and curry.
Project Euler - Problem 10 SPOILERS AHEAD.

I got the right answer, but it took several hours to run the program. Most people in the answer thread on Project Euler measured run time in milliseconds. Why does my program suck?

code:
'''Problem 10
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.

Find the sum of all the primes below two million.'''

# Define a function to determine whether a number is prime

def isPrime(num):
    prime = False

    while prime == False:
        if num == 1:
            break
        elif num == 2:
            prime = True
        else:
            for i in range (2, num):
                if num % i == 0:
                    break
                if i == num-1 and num % i != 0:
                    prime = True        
        return prime

# Find all primes under 2 million and add them to an array

allPrimes = []

for i in range (1, 2000000):
    if i % 50000 == 0:
        print i # Just so I know that it's running...
    if isPrime(i) == True:
        allPrimes.append(i)

print sum(allPrimes)

Gothmog1065
May 14, 2009
You are iterating over every single number which isn't the answer. I strugle with project euler because I struggle with math. I need to get back into it.

Here's the simplest plain english answer I've found for you.

http://code.jasonbhill.com/c/project-euler-problem-3/

Basically there are a couple of sieves you can use for prime numbers that drop numbers off of lists so that you aren't even preforming math on them. I think Sieve of Eratosthenes is the one I always landed on when doing the research.

Gothmog1065 fucked around with this message at 02:49 on Jun 9, 2015

QuarkJets
Sep 8, 2008

PongAtari posted:

Project Euler - Problem 10 SPOILERS AHEAD.

I got the right answer, but it took several hours to run the program. Most people in the answer thread on Project Euler measured run time in milliseconds. Why does my program suck?

code:
'''Problem 10
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.

Find the sum of all the primes below two million.'''

# Define a function to determine whether a number is prime

def isPrime(num):
    prime = False

    while prime == False:
        if num == 1:
            break
        elif num == 2:
            prime = True
        else:
            for i in range (2, num):
                if num % i == 0:
                    break
                if i == num-1 and num % i != 0:
                    prime = True        
        return prime

# Find all primes under 2 million and add them to an array

allPrimes = []

for i in range (1, 2000000):
    if i % 50000 == 0:
        print i # Just so I know that it's running...
    if isPrime(i) == True:
        allPrimes.append(i)

print sum(allPrimes)

To start, you can simply throw out all even numbers because you already know that all of them (except for 2) are not prime. Your algorithm is O(n^2), modifying your loops to use steps of 2 instead of steps of 1 is at least a factor of 4 improvement. You also don't need to worry about numbers between (num/2) and (num): that's another factor of 2 improvement. Actually, since you're already ignoring even numbers, technically you don't need to worry about numbers between (num/3) and num, which is even better.

From there it's just a matter of performing clever math tricks to further optimize the solution.

If you're doing this in Python2.X, then every time that you call your function you're creating a huge list; using xrange would speed that up. If you're using Python3, then that comment doesn't apply.

Other solutions might be using Numpy array or Numba compilation in order to speed up the math. But even if you don't go down that route, there are lots of things that you can do to optimize this. And therein lies the fun

ShadowHawk
Jun 25, 2000

CERTIFIED PRE OWNED TESLA OWNER

QuarkJets posted:

To start, you can simply throw out all even numbers because you already know that all of them (except for 2) are not prime. Your algorithm is O(n^2), modifying your loops to use steps of 2 instead of steps of 1 is at least a factor of 4 improvement. You also don't need to worry about numbers between (num/2) and (num): that's another factor of 2 improvement. Actually, since you're already ignoring even numbers, technically you don't need to worry about numbers between (num/3) and num, which is even better.

From there it's just a matter of performing clever math tricks to further optimize the solution.

If you're doing this in Python2.X, then every time that you call your function you're creating a huge list; using xrange would speed that up. If you're using Python3, then that comment doesn't apply.

Other solutions might be using Numpy array or Numba compilation in order to speed up the math. But even if you don't go down that route, there are lots of things that you can do to optimize this. And therein lies the fun
To determine if a number is prime, you only need to test division with other known primes up to the square root of that number.

QuarkJets
Sep 8, 2008

ShadowHawk posted:

To determine if a number is prime, you only need to test division with other known primes up to the square root of that number.

Nice. See? That's a rad math fact that should make the problem run much faster

ShadowHawk
Jun 25, 2000

CERTIFIED PRE OWNED TESLA OWNER

ShadowHawk posted:

To determine if a number is prime, you only need to test division with other known primes up to the square root of that number.
Here's my version of your isPrime function:
Python code:
def isPrime(num):
  if num == 1:
    return False

  for prime in allPrimes:
    if num % prime == 0:
      return False
  return True
Including the square root optimization:
Python code:
def isPrime(num):
  if num == 1:
    return False

  ignoreThreshold = num^0.5
  for prime in allPrimes:
    if prime > ignoreThreshold:
      return True
    if num % prime == 0:
      return False
  assert False

SurgicalOntologist
Jun 17, 2004

PongAtari posted:

Project Euler - Problem 10 SPOILERS AHEAD.

I got the right answer, but it took several hours to run the program. Most people in the answer thread on Project Euler measured run time in milliseconds. Why does my program suck?

code:
'''Problem 10
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.

Find the sum of all the primes below two million.'''

# Define a function to determine whether a number is prime

def isPrime(num):
    prime = False

    while prime == False:
        if num == 1:
            break
        elif num == 2:
            prime = True
        else:
            for i in range (2, num):
                if num % i == 0:
                    break
                if i == num-1 and num % i != 0:
                    prime = True        
        return prime

# Find all primes under 2 million and add them to an array

allPrimes = []

for i in range (1, 2000000):
    if i % 50000 == 0:
        print i # Just so I know that it's running...
    if isPrime(i) == True:
        allPrimes.append(i)

print sum(allPrimes)

It's not really a rad math fact and it won't make as big a difference as some of these other suggesions... but to get you in the habit of thinking about the minimal necessary work needed to solve the problem:

To get the sum of all those numbers, you don't actually need to save them all in a big list. Instead, keep a running total, and increment it every time you find a new prime.

ShadowHawk
Jun 25, 2000

CERTIFIED PRE OWNED TESLA OWNER

SurgicalOntologist posted:

It's not really a rad math fact and it won't make as big a difference as some of these other suggesions... but to get you in the habit of thinking about the minimal necessary work needed to solve the problem:

To get the sum of all those numbers, you don't actually need to save them all in a big list. Instead, keep a running total, and increment it every time you find a new prime.
Disagree. Saving the known primes in an ordered list is needed to use the rad math fact above :)

SurgicalOntologist
Jun 17, 2004

:doh: You're completely right of course. Saving the primes is necessary to efficiently test new primes. You (PongAtari) should keep doing it, just not for the reason you did it to begin with :)

Jewel
May 2, 2009

And by the way; Project Euler is fun but don't worry if you can't get a question! Annoyingly they're almost all math questions with some programming rather than the other way around. The best 100% "Coding" tests I've actually found were surprisingly https://www.codingame.com which actually owns and is a lot more complex than you'd realize at first.

Gothmog1065
May 14, 2009

Jewel posted:

And by the way; Project Euler is fun but don't worry if you can't get a question! Annoyingly they're almost all math questions with some programming rather than the other way around. The best 100% "Coding" tests I've actually found were surprisingly https://www.codingame.com which actually owns and is a lot more complex than you'd realize at first.

Not math? Count me in!

Lysidas
Jul 26, 2002

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

ShadowHawk posted:

Including the square root optimization:
Python code:
def isPrime(num):
  if num == 1:
    return False

  ignoreThreshold = num^0.5
  for prime in allPrimes:
    if prime > ignoreThreshold:
      return True
    if num % prime == 0:
      return False
  assert False

FYI ^ is bitwise XOR, not exponentiation.

Opulent Ceremony
Feb 22, 2012

QuarkJets posted:

If you're doing this in Python2.X, then every time that you call your function you're creating a huge list; using xrange would speed that up. If you're using Python3, then that comment doesn't apply.

What's 3 doing differently?

vikingstrike
Sep 23, 2007

whats happening, captain

Opulent Ceremony posted:

What's 3 doing differently?

Treating range() like xrange() from python 2, I think.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

vikingstrike posted:

Treating range() like xrange() from python 2, I think.

Yes

quote:

ActivePython 2.7.0.2 (ActiveState Software Inc.) based on
Python 2.7 (r27:82500, Aug 23 2010, 17:17:51) [MSC v.1500 64 bit (AMD64)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> range(9)
[0, 1, 2, 3, 4, 5, 6, 7, 8]
>>> xrange(9)
xrange(9)
>>> from __future__ import print_function
>>> print(*xrange(9))
0 1 2 3 4 5 6 7 8
>>>

quote:

Python 3.4.2 (v3.4.2:ab2c023a9432, Oct 6 2014, 22:15:05) [MSC v.1600 32 bit (In
tel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> range(9)
range(0, 9)
>>> print(*range(9))
0 1 2 3 4 5 6 7 8
>>>

FoiledAgain
May 6, 2007

PyQt question: How do I find out which row a user has selected in a QTable?

edit: n/m I see the dumb thing I did - QModelIndex is the only member of a list that is being returned.

FoiledAgain fucked around with this message at 21:09 on Jun 9, 2015

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

Gothmog1065 posted:

Not math? Count me in!

Also look at Reddit's Daily Programming Challenges. The range from Easy, Intermediate and Hard on a variety of topics.

ShadowHawk
Jun 25, 2000

CERTIFIED PRE OWNED TESLA OWNER

Lysidas posted:

FYI ^ is bitwise XOR, not exponentiation.
pfft, actually testing code is for scrubs

Gothmog1065
May 14, 2009

Hughmoris posted:

Also look at Reddit's Daily Programming Challenges. The range from Easy, Intermediate and Hard on a variety of topics.

I might look at that in concurrence with the codingame, but I"m loving codingame as I don't have to math all that much. However, I think I've written myself into a corner. I might be misunderstanding while.

Basically this is the "Move Thor to the right spots" game. It gives you Thor's starting locations and the locations of the lightning thing. However, I'm having some difficulty with Thor's "current position. It never updates past his initial position. Here's the code:

Python code:
import sys, math

# Auto-generated code below aims at helping you parse
# the standard input according to the problem statement.
# ---
# Hint: You can use the debug stream to print initialTX and initialTY, if Thor does not follow your orders.

# LX: the X position of the light of power
# LY: the Y position of the light of power
# initialTX: Thor's starting X position
# initialTY: Thor's starting Y position
LX, LY, initialTX, initialTY = [int(i) for i in input().split()]

# game loop
while 1:
    E = int(input()) # The level of Thor's remaining energy, representing the number of moves he can still make.
    
    # Write an action using print
    # To debug: print("Debug messages...", file=sys.stderr)
    
    x_directions = {"0" : ("",0),
                    "N" : ("E",1),
                    "P" : ("W",-1)}
    y_directions = {"0" : ("",0),
                    "P" : ("N",-1),
                    "N" : ("S",1)}
    start = 0
    
    def find_path(LX, LY, tx,ty): #Find Thor's path
        
        pos_checkx, pos_checky = x_directions[is_positive(tx,LX)], y_directions[is_positive(ty,LY)]
        x_val,x_move =  pos_checkx[0],pos_checkx[1]
        y_val,y_move =  pos_checky[0],pos_checky[1]
        
        #Determines if the move is out of bounds and resets if it is.
        
        print("Checking Bounds: " + str(ty) + " " + str(y_move), file=sys.stderr)
        #print("X: " + str(bound_check(tx, x_move, "x")),  file=sys.stderr)
        if bound_check(tx, x_move, "x") != 1: 
            x_val = ""
            #print("X Value Reset", file=sys.stderr)
        
        print("Y: " + str(bound_check(ty, y_move, "y")),  file=sys.stderr)    
        if bound_check(ty, y_move, "y") != 1:
            y_val = ""
            #print(ty, y_move, file=sys.stderr)
            #print("Y Value Reset", file=sys.stderr)
        
        ret = ( y_val + x_val , tx + x_move , ty + y_move) #Move, x, y
        
        print("Find Path Retun values: " + str(ret), file=sys.stderr)
        return ret
        
    def is_positive(num1, num2):
        #check to see if the way thor is going is going to be a positive or negative direction
        if num1 - num2 == 0:
            return "0"
        elif num1 - num2 < 0:
            return "N"
        elif num1 - num2 > 0:
            return "P"
        else:
            return "0"
    
    #checks boundaries and stops Thor from going out. 
    def bound_check(location, direction, axis):
        new_location = location + direction
        
        if axis == "y":
            if 0 <= new_location < 18:
                return 1
                
        elif axis == "x":
            if 0 <= new_location < 40:
                return 1
        else: 
            return 0
        
    if start == 0:
        currentTX, currentTY = initialTX, initialTY
        start += 1
        
    pathing = find_path(LX, LY, currentTX, currentTY)
    print(currentTX, currentTY, pathing, file=sys.stderr)
    move, currentTX, currentTY = pathing[0], pathing[1], pathing[2]
    
    print(move)
What is the obvious thing I'm missing? I know the code is rough and eventually I hope to be doing things better than this as I learn more ticks and trips.

hooah
Feb 6, 2006
WTF?
Well, you sure made that a lot more complicated than I at least did (I've been enjoying CodinGame as well)!

I'm having some trouble understanding your functions and whatnot since you've decided to pack everything up so much, but the problem I had with the Thor one was that I wasn't updating my program's knowledge of Thor's position when he moves. Are you doing this?

Gothmog1065
May 14, 2009

hooah posted:

Well, you sure made that a lot more complicated than I at least did (I've been enjoying CodinGame as well)!

I'm having some trouble understanding your functions and whatnot since you've decided to pack everything up so much, but the problem I had with the Thor one was that I wasn't updating my program's knowledge of Thor's position when he moves. Are you doing this?

I thought I was doing that here (the return adds the "move" to the coordinates supposedly), but it's not updating. Probably because I'm doing something wrong. I'm also thinking of putting the coordinates in as a simple list (x,y).

Python code:
    pathing = find_path(LX, LY, currentTX, currentTY)
    print(currentTX, currentTY, pathing, file=sys.stderr)
    move, currentTX, currentTY = pathing[0], pathing[1], pathing[2]
I'm still new so I've got tons to learn but that's why i'm here hopefully.

hooah
Feb 6, 2006
WTF?
I dunno, I just did a bunch of if/elifs based on the difference between Thor's location and the light thing's location.

What I ended up doing for a couple other easy-level ones was firing up PyCharm so I could do some proper debugging. That might help a lot.

Jewel
May 2, 2009

Once you get it working, here's my Thor program's equivalent in python, for reference:

Python code:
def sign(n):
	if (n > 0): return 1
	elif (n < 0): return -1
	
	return 0

endX, endY, x, y = [int(i) for i in r().split()]

while 1:
	E = int(raw_input()) # I forgot what this was used for. Energy? Either way I don't use it
	
	dx = sign(endX-x) #Delta x
	dy = sign(endY-y) #Delta y
	
	o = ""
	
	#Go north or south
	if (dy < 0): o += "N"
	elif (dy > 0): o += "S"
	
	#Go east or west
	if (dx < 0): o += "W"
	elif (dx > 0): o += "E"
	
	print o
	
	x+=dx
	y+=dy
Or the horrible code-golf version I had to write

Python code:
a,b,x,y=[int(i) for i in raw_input().split()]
while 1:j=cmp(a-x,0);k=cmp(b-y,0);print (("S","N")[k<0],"")[k==0]+(("E","W")[j<0],"")[j==0];x+=j;y+=k
:shepface:

Helado
Mar 7, 2004

The while loop gets executed after every move you output and it only passes in the "energy" level. So you need to store your own internal version of where you think Thor is. This also means you can move your function defs outside of the while loop. In general, as far as I can tell, all you're missing is keeping track of where do YOU think Thor is after printing out the command direction, since the game doesn't give you that information except for the starting position.

The structure of the program is basically:
code:
get starting and ending positions
while we have energy
    do a move
    store new position
The test framework will bomb you out if you use up too much energy.

edit:
I see you are doing that with currentX and currentY, but you are overriding it because start gets reset to 0 at the top of your loop. Move "start = 0" from inside to outside of the while.

Helado fucked around with this message at 23:42 on Jun 10, 2015

Gothmog1065
May 14, 2009

Helado posted:

The while loop gets executed after every move you output and it only passes in the "energy" level. So you need to store your own internal version of where you think Thor is. This also means you can move your function defs outside of the while loop. In general, as far as I can tell, all you're missing is keeping track of where do YOU think Thor is after printing out the command direction, since the game doesn't give you that information except for the starting position.

The structure of the program is basically:
code:
get starting and ending positions
while we have energy
    do a move
    store new position
The test framework will bomb you out if you use up too much energy.

edit:
I see you are doing that with currentX and currentY, but you are overriding it because start gets reset to 0 at the top of your loop. Move "start = 0" from inside to outside of the while.

Aha! I was thinking of doing that last night, and completely missed the overriding start part. I knew it was something dumb. Is it better to move all my functions outside of the loop in general? Once the program is working, I'm going to work on trimming it down to a smaller and less overworked size.

hooah
Feb 6, 2006
WTF?

Gothmog1065 posted:

Is it better to move all my functions outside of the loop in general?

As far as I'm aware, yes, it's better to separate your functions from your main program/function in all programming languages (although I only have experience with C/C++ and Python).

Cingulate
Oct 23, 2012

by Fluffdaddy

hooah posted:

As far as I'm aware, yes, it's better to separate your functions from your main program/function in all programming languages (although I only have experience with C/C++ and Python).
Are there any exceptions to this rule?

For example, one thing I sometimes do is

code:
def some_function(input):
    if has_some_characteristic(input):
        def do_something(x):
            return whatever(x)
    else:
        def do_something(x):
            return something_else(x)

    x = do_things_with(input)
    return do_something(x)

Gothmog1065
May 14, 2009

Jewel posted:

Once you get it working, here's my Thor program's equivalent in python, for reference:

I finally ended up with:

Python code:
import sys, math

LX, LY, initialTX, initialTY = [int(i) for i in input().split()]
currentTX, currentTY = initialTX, initialTY

    
def find_path(LX, LY, tx,ty): #Find Thor's path
        
    x_move, y_move = is_positive(LX,tx), is_positive(LY,ty)
    move = ""

    if y_move < 0:
        move += "N"
    elif y_move > 0:
        move += "S"
        
    if x_move < 0:
        move += "W"
    elif x_move > 0:
        move += "E"

    #Determines if the move is out of bounds and resets if it is.
    if bound_check(tx, x_move, "x") != 1: 
        x_val = ""
    
    if bound_check(ty, y_move, "y") != 1:
        y_val = ""
        
    ret = ( move , tx + x_move , ty + y_move) #Move direction, new x, new y
    return ret
        
def is_positive(num1, num2):
    #check to see if the way thor is going is going to be a positive or negative direction
    if num1 - num2 < 0:
        return -1
    elif num1 - num2 > 0:
        return +1
    else:
        return 0
    
#checks boundaries and stops Thor from going out. 
def bound_check(location, direction, axis):
    new_location = location + direction
        
    if axis == "y":
        if 0 <= new_location < 18:
            return 1
                
    elif axis == "x":
        if 0 <= new_location < 40:
            return 1
    else: 
        return 0

# game loop
while 1:
    #E is totally useless, probably for people who go straight and not diagonal. 
    E = int(input()) # The level of Thor's remaining energy, representing the number of moves he can still make.
    
    pathing = find_path(LX, LY, currentTX, currentTY)
    move, currentTX, currentTY = pathing[0], pathing[1], pathing[2]
    
    print(move)
I think if I kept going further, I would have ended up somewhere close to yours, except for maybe how the final variables played out. I'll try to get close to that on the next one!

SurgicalOntologist
Jun 17, 2004

Cingulate posted:

Are there any exceptions to this rule?

For example, one thing I sometimes do is

code:
def some_function(input):
    if has_some_characteristic(input):
        def do_something(x):
            return whatever(x)
    else:
        def do_something(x):
            return something_else(x)

    x = do_things_with(input)
    return do_something(x)

I see this a lot and either it's dependent on nested namespaces, which gets hairy, or it's just sloppy. For example here you could just do:

Python code:
def do_something_one_way(x):
    return whatever(x)

def do_something_another_way(x):
    return something_else(x)

def some_function(input):
    doer = do_something_one_way if has_characteristic(input) else do_something_another_way

    x = do_things_with(input)
    return doer(x)
In other words, either those functions don't have to be nested at all, or you're abusing local/global namespaces and will (someday) regret it.

hooah
Feb 6, 2006
WTF?

Cingulate posted:

Are there any exceptions to this rule?

For example, one thing I sometimes do is

code:
def some_function(input):
    if has_some_characteristic(input):
        def do_something(x):
            return whatever(x)
    else:
        def do_something(x):
            return something_else(x)

    x = do_things_with(input)
    return do_something(x)

I'm not an expert by any means, but why define functions within functions, rather than defining them elsewhere and calling them as needed? I guess I could see an argument if you're tight on memory, but you'd probably be more likely to be using C anyway in that case.

Nippashish
Nov 2, 2005

Let me see you dance!
Closures are super powerful and you should use them. They let you do stuff like this:

code:
def make_batch_factory(batch_size):
    def batch_factory():
        batch = do stuff with batch_size
        return batch_size 
    return batch_factory

SurgicalOntologist
Jun 17, 2004

Ah, yes, I would make an exception for functions that return a function.

Helado
Mar 7, 2004

Gothmog1065 posted:

Aha! I was thinking of doing that last night, and completely missed the overriding start part. I knew it was something dumb. Is it better to move all my functions outside of the loop in general? Once the program is working, I'm going to work on trimming it down to a smaller and less overworked size.

Others have already responded, but I'll add, that based on where you're probably at on learning, you will almost always want to keep your function definitions outside of other things (other functions, loops, etc). There are some neat things and reasons for defining functions inside other scopes, but until you really need to, you're better off keeping functions 'global'. For example, it would have probably been easier to see where your problem was with that start variable if you didn't have all that extra code somewhere it doesn't have to be. It also would be easier for you to test the function independently of the surrounding code.

Adbot
ADBOT LOVES YOU

king salmon
Oct 30, 2011

by Cowcaster
It's also going to slow down your program a lot if you define functions inside loops or other things that get evaluated repeatedly (if you need to care about speed at all).

  • Locked thread