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
tef
May 30, 2004

-> some l-system crap ->

trekdanne posted:

I ran into this "problem" with Python scoping. I know that Python uses statical scoping but that doesn't really work that well with the lambda keyword.

What does the following program output?
code:
a = []
for i in xrange(5):
	a.append(lambda x: i + x)

print a[1](1)
a) 2
b) 5
c) -1

Answer: b) 5

the i is stored in the outer scope, and not copied into the lambda, so i keeps the value from exiting the loop.

code:
a = []
for i in xrange(5):
	a.append(lambda x, i=i: i + x)

print a[1](1)
happy now ?

tef fucked around with this message at 11:49 on Jul 20, 2013

Adbot
ADBOT LOVES YOU

prefect
Sep 11, 2001

No one, Woodhouse.
No one.




Dead Man’s Band

tef posted:

code:
i=i

:eyepop:

double sulk
Jul 2, 2010


pop(i)

weird
Jun 4, 2012

by zen death robot

trekdanne posted:

I ran into this "problem" with Python scoping. I know that Python uses statical scoping but that doesn't really work that well with the lambda keyword.

What does the following program output?
code:
a = []
for i in xrange(5):
	a.append(lambda x: i + x)

print a[1](1)
a) 2
b) 5
c) -1

Answer: b) 5

these loop 4 times so i will he 4 after the loop completes
code:
CL-USER> (let ((a nil))
	   (dotimes (i 4 (funcall (cadr (reverse a)) 1))
	     (push (lambda (x) (+ i x)) a)))
5
code:
#;1> (do ((i 0 (+ i 1))
          (a '() (cons (lambda (x) (+ i x)) a)))
         ((= i 4) ((cadr (reverse a)) 1)))
2
scheme is cool

Symbolic Butt
Mar 22, 2009

(_!_)
Buglord

tef posted:

the i is stored in the outer scope, and not copied into the lambda, so i keeps the value from exiting the loop.

code:
a = []
for i in xrange(5):
	a.append(lambda x, i=i: i + x)

print a[1](1)
happy now ?

code:
a = []
for i in xrange(5):
    if i == 3: a.append(lambda x: i + x)

print a[0](1)  # 5
oh my goooooood

ok I'm happy now.

MeruFM
Jul 27, 2010

tef posted:

the i is stored in the outer scope, and not copied into the lambda, so i keeps the value from exiting the loop.

code:
a = []
for i in xrange(5):
	a.append(lambda x, i=i: i + x)

print a[1](1)
happy now ?

to be honest, this makes sense
anonymous functions should not store unless explicitly declared

but it also means that function and statefulness do not mix

MeruFM
Jul 27, 2010
code:
a = []
j = 10
for i in xrange(5):
    if i == 2: a.append(lambda x: j + x)

j = 5
print a[0](1)  # 6
all is right
i don't have to stealth edit

tef
May 30, 2004

-> some l-system crap ->

:getin:

Greed is eternal
Jun 8, 2008

tef posted:

happy now ?

I am still programming in Python, so the awswer is NOOO.

Elder Postsman
Aug 30, 2000


i used hot bot to search for "teens"

i wrote some python today, can y'all tell me how bad it is (it's bad because it's python but i mean besides that)

this first one takes a qa flag layer like this:

code:
OBJECTID	SHAPE	TYPE	COMMENTS	FEATURECLASS		FEAT_OID	STATUS
1		POINT	0	Disconnected	SupportStructure	1234		0
2		POINT	0	Disconnected	Fuse			4532		0
3		POINT	0	Disconnected	Switch			8633		0
4		POINT	0	Disconnected	SupportStructure	2523		0
5		POINT	0	Disconnected	Transformer		523		0
and selects the flagged features and outputs the selection to an xml. i even used elementtree to make the xml in a not-stupid way like i was before

Python code:
import arcpy, xml.etree.cElementTree as et
arcpy.env.overwriteOutput = True

savePath = arcpy.GetParameterAsText(0)
QAException = arcpy.GetParameterAsText(1)

outFile = open(savePath, 'w')

def getValueList(flag, field):
    values = set()
    rows = arcpy.SearchCursor(flag)
    for row in rows:
        values.add(row.getValue(field))
    valueslist = list(values)
    return valueslist

root = et.Element("Selection")

featureList = getValueList(QAException, "FEATURECLASS")

for featurename in featureList:
    QAFeature = arcpy.MakeFeatureLayer_management(QAException, "QAFeatureLayer", "FeatureClass = '" + str(featurename) + "'")
    fcline = et.SubElement(root, "FeatureClass", {"name":str(featurename), "oid_field":"ObjectID"})
    featoidlist = getValueList(QAFeature, "FEAT_OID")
    if len(featoidlist) > 1:
        qry = "OBJECTID in " + str(tuple(featoidlist))
    else:
        qry = "OBJECTID = " + str(featoidlist[0])
    for featoid in featoidlist:
        fline = et.SubElement(fcline, "Feature", {"oid":str(featoid)})    
    arcpy.SelectLayerByAttribute_management(featurename, "NEW_SELECTION", qry)

et.ElementTree(root).write(outFile)
so that would select those features from those featureclasses, and put out an xml like

code:
<Selection>
	<FeatureClass name="SupportStructure" oid_field="OBJECTID">
		<Feature oid="1234" />
		<Feature oid="2423" />
	</FeatureClass>
	<FeatureClass name="Fuse" oid_field="OBJECTID">
		<Feature oid="4532" />
	</FeatureClass>
	<FeatureClass name="Switch" oid_field="OBJECTID">
		<Feature oid="8633" />
	</FeatureClass>
	<FeatureClass name="Transformer" oid_field="OBJECTID">
		<Feature oid="523" />
	</FeatureClass>
</Selection>
and then this one takes that xml and selects those features. so for example you can recreate that selection on another computer or whatever

Python code:
import arcpy, xml.etree.cElementTree as et

xmlfile = arcpy.GetParameterAsText(0)

content = et.ElementTree(file=xmlfile)
selection = content.getroot()

for featureclass in selection:
    currentfeature = featureclass.attrib.get('name')
    oidlist = []
    for feature in featureclass:
        oidlist.append(feature.attrib.get('oid'))
        if len(oidlist) > 1:
            qry = "OBJECTID in " + str(tuple(oidlist)).replace("'", "")
        else:
            qry = "OBJECTID = " + str(oidlist[0]).replace("'", "")
    arcpy.SelectLayerByAttribute_management(currentfeature, "NEW_SELECTION", qry)

PleasingFungus
Oct 10, 2012
idiot asshole bitch who should fuck off

dur posted:

i wrote some python today, can y'all tell me how bad it is (it's bad because it's python but i mean besides that)

honestly, it looks generally fine. not familiar with arcpy, but nothing there looks obviously wrong.

I'd probably rewrite getValueList() as:

Python code:
def getValueList(flag, field):
    return list(set(row.getValue(field) for row in arcpy.SearchCursor(flag)))
and that's about it.

prefect
Sep 11, 2001

No one, Woodhouse.
No one.




Dead Man’s Band

PleasingFungus posted:

Python code:
def getValueList(flag, field):
    return list(set(row.getValue(field) for row in arcpy.SearchCursor(flag)))

i think that looks pretty cool, but i am also fond of perl, so you might want to reconsider that code :D

PleasingFungus
Oct 10, 2012
idiot asshole bitch who should fuck off

prefect posted:

i think that looks pretty cool, but i am also fond of perl, so you might want to reconsider that code :D

eh, it's pretty idiomatic. grab an iterator, map a single function on it, feed that into a set and then into a list. it's admittedly borderline - one more operation, and I'd definitely want to split it onto multiple lines - but I think it's ok.

actually, on further consideration, this is probably about right:

Python code:
def getValueList(flag, field):
    valueSet = set(row.getValue(field) for row in arcpy.SearchCursor(flag))
    return list(valueSet)

uG
Apr 23, 2003

by Ralp
seems like you could use a map and unpack if you want to go with new-skool self documenting, as few lines as possible, but i dont use python

Posting Principle
Dec 10, 2011

by Ralp

PleasingFungus posted:

eh, it's pretty idiomatic. grab an iterator, map a single function on it, feed that into a set and then into a list. it's admittedly borderline - one more operation, and I'd definitely want to split it onto multiple lines - but I think it's ok.

actually, on further consideration, this is probably about right:

Python code:
def getValueList(flag, field):
    valueSet = set(row.getValue(field) for row in arcpy.SearchCursor(flag))
    return list(valueSet)

can you just use a set comprehension on that first line?

PleasingFungus
Oct 10, 2012
idiot asshole bitch who should fuck off

Jerry SanDisky posted:

can you just use a set comprehension on that first line?

yes, I literally did two posts up from the one you quoted. but then I decided that it was too many things going on in one line, and split it up to make it easier to read.

dur's original code was

Python code:
def getValueList(flag, field):
    values = set()
    rows = arcpy.SearchCursor(flag)
    for row in rows:
        values.add(row.getValue(field))
    valueslist = list(values)
    return valueslist
but that was on too many lines, and actually made it harder to read. like writing

Java code:
int i;
i = 0;
int bound = arr.length - 1
while (i < bound) {
    arr[i] = arr[i+1];
    i++;
}
instead of
Java code:
for (int i = 0; i < arr.length - 1; i++)
    arr[i] = arr[i+1];
it's a balance, and admittedly something of a personal judgment - different people will have different opinions on what's easy to read. (some people still believe in the 80-character limit!) but I think I'm right, and that's what matters.

Posting Principle
Dec 10, 2011

by Ralp

PleasingFungus posted:

yes, I literally did two posts up from the one you quoted. but then I decided that it was too many things going on in one line, and split it up to make it easier to read.


no, calling set() on a list comprehension is not a set comprehension

tef
May 30, 2004

-> some l-system crap ->
ps should i make a smart dog book thread in CoC and then argue about stuff?

tef
May 30, 2004

-> some l-system crap ->

Jerry SanDisky posted:

no, calling set() on a list comprehension is not a set comprehension

(ps technically he called it on a generator comprehension).

(pps you don't need to return a list, a set would be fine I think)

PleasingFungus
Oct 10, 2012
idiot asshole bitch who should fuck off
just noticed something else:

Python code:
    for feature in featureclass:
        oidlist.append(feature.attrib.get('oid'))
        if len(oidlist) > 1:
            qry = "OBJECTID in " + str(tuple(oidlist)).replace("'", "")
        else:
            qry = "OBJECTID = " + str(oidlist[0]).replace("'", "")
    arcpy.SelectLayerByAttribute_management(currentfeature, "NEW_SELECTION", qry)
the 'if len(oidlist)/else' block should probably be decremented one setp; no reason to do it until you've finished building oidlist. also... are you turning oidlist into a tuple so you get parens instead of square brackets? :allears:

actually, now that I'm looking at it

Python code:
...
    def feature_to_oidstr(feature):
        oid = feature.attrib.get('oid')
        return str(oid).replace("'", '')
    oidstrlist = [feature_to_oidstr(feature) for feature in featureclass]

    if len(oidstrlist) > 1:
        qry = "OBJECTID in ({})".format(','.join(oidstrlist))
    else:
        qry = "OBJECTID = " + oidstrlist[0] #this will throw an exception if there are no oids in the featureclass

    arcpy.SelectLayerByAttribute_management(currentfeature, "NEW_SELECTION", qry)
more lines, but clears up some silliness with the strings slightly, maybe.

honestly I just like playing with python and list comprehensions. I admit it.

Jerry SanDisky posted:

no, calling set() on a list comprehension is not a set comprehension

o

oops

yeah, that's a reasonable tweak

coffeetable
Feb 5, 2006

TELL ME AGAIN HOW GREAT BRITAIN WOULD BE IF IT WAS RULED BY THE MERCILESS JACKBOOT OF PRINCE CHARLES

YES I DO TALK TO PLANTS ACTUALLY

tef posted:

ps should i make a smart dog book thread in CoC and then argue about stuff?

yes

even if it's exhausting for you, it'll be educational for the rest of us

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder

tef posted:

ps should i make a smart dog book thread in CoC and then argue about stuff?

make one here

PleasingFungus
Oct 10, 2012
idiot asshole bitch who should fuck off

tef posted:

(ps technically he called it on a generator comprehension).

(pps you don't need to return a list, a set would be fine I think)

I thought that at first, but then I noticed this bit

Python code:
    featoidlist = getValueList(QAFeature, "FEAT_OID")
    if len(featoidlist) > 1:
        qry = "OBJECTID in " + str(tuple(featoidlist))
    else:
        qry = "OBJECTID = " + str(featoidlist[0])
the last line being the relevant one

you could rewrite that bit, but I was trying for a minimum-impact change.


tef posted:

ps should i make a smart dog book thread in CoC and then argue about stuff?

yes

then link it here or in the other programming thread

Posting Principle
Dec 10, 2011

by Ralp

tef posted:

(ps technically he called it on a generator comprehension).


why am i so loving bad at python :eng99:

anyways, i'm sure you will explain why, but the set comprehension is reliably faster on my machine given these fake functions

Python code:
#alist is 1000 random ints generated before hand
def foo_set():
	return list(set(x**2 for x in alist)) 

def foo_comp():
	return list({x**2 for x in alist})
code:
>>> cProfile.run('for i in range(100000): foo_set()')
         100200003 function calls in 59.634 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   100000   13.401    0.000   59.078    0.001 <stdin>:1(foo_set)
100100000   45.677    0.000   45.677    0.000 <stdin>:2(<genexpr>)
        1    0.556    0.556   59.634   59.634 <string>:1(<module>)
        1    0.000    0.000   59.634   59.634 {built-in method exec}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Prof
iler' objects}


>>> cProfile.run('for i in range(100000): foo_comp()')
         200003 function calls in 46.887 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   100000    1.720    0.000   46.340    0.000 <stdin>:1(foo_comp)
   100000   44.620    0.000   44.620    0.000 <stdin>:2(<setcomp>)
        1    0.547    0.547   46.887   46.887 <string>:1(<module>)
        1    0.000    0.000   46.887   46.887 {built-in method exec}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Prof
iler' objects}

Posting Principle
Dec 10, 2011

by Ralp
i'm gonna write some python and dig into python source cuz im just embarassing myself

Shaggar
Apr 26, 2006
switch 2 java or c# ftw

PleasingFungus
Oct 10, 2012
idiot asshole bitch who should fuck off

Jerry SanDisky posted:

why am i so loving bad at python :eng99:

anyways, i'm sure you will explain why, but the set comprehension is reliably faster on my machine given these fake functions

you got that backwards, the set comprehension is orders of magnitude slower per your numbers

gently caress if I know why, though

Shaggar posted:

switch 2 java or c# ftw

Posting Principle
Dec 10, 2011

by Ralp

PleasingFungus posted:

you got that backwards, the set comprehension is orders of magnitude slower per your numbers

gently caress if I know why, though

foo_comp uses the set comprehension, foo_set uses the set() builtin. they both ran 100k times and foo_comp took 13 seconds less??

PleasingFungus
Oct 10, 2012
idiot asshole bitch who should fuck off

Jerry SanDisky posted:

foo_comp uses the set comprehension, foo_set uses the set() builtin. they both ran 100k times and foo_comp took 13 seconds less??

oh, I was misreading it.

I think I might just be really bad at reading your posts.

PleasingFungus
Oct 10, 2012
idiot asshole bitch who should fuck off

PleasingFungus posted:

I think I might just be really bad.

Elder Postsman
Aug 30, 2000


i used hot bot to search for "teens"

PleasingFungus posted:

honestly, it looks generally fine. not familiar with arcpy, but nothing there looks obviously wrong.

I'd probably rewrite getValueList() as:

Python code:
def getValueList(flag, field):
    return list(set(row.getValue(field) for row in arcpy.SearchCursor(flag)))
and that's about it.

yeah i like that a lot better, like you said it's a lot easier to read too. i think i did it the first way because i thought valuelist was the name of the thing the function returned (because i'm new to this whole programming thing)

PleasingFungus posted:

the 'if len(oidlist)/else' block should probably be decremented one setp; no reason to do it until you've finished building oidlist. also... are you turning oidlist into a tuple so you get parens instead of square brackets? :allears:

qry = "OBJECTID = " + oidstrlist[0] #this will throw an exception if there are no oids in the featureclass

well the selectlayerbyattributes query needs things to be in parenthesis, not square brackets. that's how someone else on the arcgis.com forums did it so i stole it. and also there will always be oids in the featureclass.

tef
May 30, 2004

-> some l-system crap ->
i'm guessing that the set-comprehension is mostly implemented in C, so python can go woosh. with the generator comprehension, some extra work is done, and a bit of indirection to build the set.

PleasingFungus
Oct 10, 2012
idiot asshole bitch who should fuck off

dur posted:

well the selectlayerbyattributes query needs things to be in parenthesis, not square brackets. that's how someone else on the arcgis.com forums did it so i stole it.

that is extremely silly, and certainly bad practice, but I can't bring myself to be upset about it. (the teddy in your av probably helps. :3:)

the post you quoted suggests one way to be a little more explicit about what you're doing vis-a-vis string formatting:

Python code:
            qry = "OBJECTID in ({})".format(','.join(oidstrlist))
build a comma-separated list of elements, then drop 'em between parens. it's the same result as the tuple approach, just expresses your intent more clearly in code, rather than indirectly indicating it by switching data structures.

Symbolic Butt
Mar 22, 2009

(_!_)
Buglord

tef posted:

ps should i make a smart dog book thread in CoC and then argue about stuff?
yes

prefect posted:

i think that looks pretty cool, but i am also fond of perl, so you might want to reconsider that code :D
the comprehension idiom is a strong thing in python (it's super fast) and in the case where it might have too many for loops and ifs you can just break it in different lines and it still looks very readable!

Python code:
    return next((WATER, ZEBRA)
                for (red, green, ivory, yellow, blue) in c(orderings)
                if imright(green, ivory)
                for (Englishman, Spaniard, Ukranian, Japanese, Norwegian) in c(orderings)
                if Englishman is red
                if Norwegian is first
                if nextto(Norwegian, blue)
                for (coffee, tea, milk, oj, WATER) in c(orderings)
                if coffee is green
                if Ukranian is tea
                if milk is middle
                for (OldGold, Kools, Chesterfields, LuckyStrike, Parliaments) in c(orderings)
                if Kools is yellow
                if LuckyStrike is oj
                if Japanese is Parliaments
                for (dog, snails, fox, horse, ZEBRA) in c(orderings)
                if Spaniard is dog
                if OldGold is snails
                if nextto(Chesterfields, fox)
                if nextto(Kools, horse)
                )
with that said I couldn't convince anyone irl of how great comprehensions are, even after I show this example from Peter Norvig's code. :(

everybody is exactly like "I don't need this perl poo poo in my python"

Workaday Wizard
Oct 23, 2009

by Pragmatica

Symbolic Butt posted:

yes

the comprehension idiom is a strong thing in python (it's super fast) and in the case where it might have too many for loops and ifs you can just break it in different lines and it still looks very readable!

Python code:
    return next((WATER, ZEBRA)
                for (red, green, ivory, yellow, blue) in c(orderings)
                if imright(green, ivory)
                for (Englishman, Spaniard, Ukranian, Japanese, Norwegian) in c(orderings)
                if Englishman is red
                if Norwegian is first
                if nextto(Norwegian, blue)
                for (coffee, tea, milk, oj, WATER) in c(orderings)
                if coffee is green
                if Ukranian is tea
                if milk is middle
                for (OldGold, Kools, Chesterfields, LuckyStrike, Parliaments) in c(orderings)
                if Kools is yellow
                if LuckyStrike is oj
                if Japanese is Parliaments
                for (dog, snails, fox, horse, ZEBRA) in c(orderings)
                if Spaniard is dog
                if OldGold is snails
                if nextto(Chesterfields, fox)
                if nextto(Kools, horse)
                )
with that said I couldn't convince anyone irl of how great comprehensions are, even after I show this example from Peter Norvig's code. :(

everybody is exactly like "I don't need this perl poo poo in my python"

as someone who doesn't use python that syntax looks awful

i can't tell what i'm looking at (did you mess up the indentation or something?)

can someone explainn to me

PleasingFungus
Oct 10, 2012
idiot asshole bitch who should fuck off

Shinku ABOOKEN posted:

as someone who doesn't use python that syntax looks awful

i can't tell what i'm looking at (did you mess up the indentation or something?)

can someone explainn to me

as someone who uses python & loves list comprehensions, I am baffled and faintly horrified. that code is incomprehensible.

I'll second the question re indentation.

nrook
Jun 25, 2009

Just let yourself become a worthless person!
I think it's God's own code

you can tell because it's ineffable

PleasingFungus
Oct 10, 2012
idiot asshole bitch who should fuck off
googling finds context: it's a fragment of a program that solves the Zebra Puzzle

specifically, it's a fragment of one of these programs; though notably, these two are also both incomplete.

still looking at indentation. I tried a few different variants, but they were clearly both (a) wrong and (b) broke tables.

PleasingFungus fucked around with this message at 04:54 on Jul 24, 2013

PleasingFungus
Oct 10, 2012
idiot asshole bitch who should fuck off
okay, got it, maybe. it iterates over assignments of (house number) permutations to elements, filtering out impossibilities at each stage; at the end, an iterator is returned that only yields one element, the solution.

Python code:
return next(
	(
		(
			(
				(
					(WATER, ZEBRA) for (red, green, ivory, yellow, blue) in c(orderings) if imright(green, ivory)
				) for (Englishman, Spaniard, Ukranian, Japanese, Norwegian) in c(orderings) if Englishman is red if Norwegian is first if nextto(Norwegian, blue)
			) for (coffee, tea, milk, oj, WATER) in c(orderings) if coffee is green if Ukranian is tea if milk is middle
		) for (OldGold, Kools, Chesterfields, LuckyStrike, Parliaments) in c(orderings) if Kools is yellow if LuckyStrike is oj if Japanese is Parliaments
	) for (dog, snails, fox, horse, ZEBRA) in c(orderings) if Spaniard is dog if OldGold is snails if nextto(Chesterfields, fox) if nextto(Kools, horse)
)
flow proceeds first from bottom to top (the bottom/outermost iterator requesting a yield from the one above, etc), then top to bottom repeatedly (as the top/innermost iterator yields a permutation, which proceeds downward, matching with other permutations until a filter rejects, at which point control steps up a level, etc); the top iterator yields many times, the bottom iterator only once.

in the end, a pruned subset of P(5)^5 = ~25E9 possibilities are examined; the code is from an attempt to minimize on possibilities examined.

that only took 35 minutes to figure out. good code!

Adbot
ADBOT LOVES YOU

Symbolic Butt
Mar 22, 2009

(_!_)
Buglord
:smith: oh well

it looks good to me and understandable for those kinds of brute-force things and also very convenient to tinker and reorder the loops. it's not very natural at first but I guess I got used with the bottom-up flow from comprehensions? something huge like this rarely came up for me besides challenge problems though

but yeah I guess I gotta rethink this stuff

  • Locked thread