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
Spime Wrangler
Feb 23, 2003

Because we can.

Stabby McDamage posted:

I'm surprised nobody's posted the underlying problem.

It's common to all floating-point arithmetic. Basically, as with integers, the number is stored using a binary representation.
Thanks. I figured this was the root cause but I didn't know if there was some standard way of avoiding it or if it was just accepted as a fact of life.

Adbot
ADBOT LOVES YOU

Modern Pragmatist
Aug 20, 2008

Avenging Dentist posted:

I know why it's that way but it's beyond retarded that they don't check for it in the assignment, especially since it's trivially easy (A[3::-1].base is A).

Do you mind elaborating why this is the case? Is it because you don't want to unnecessarily copy the entire array in memory? What benefits does the current way have?

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

Modern Pragmatist posted:

Do you mind elaborating why this is the case? Is it because you don't want to unnecessarily copy the entire array in memory? What benefits does the current way have?

NumPy array slices are just views into the array and reference the same memory. It's faster and more memory-efficient. This is a dumb bug because it's actually something that C/C++ programmers have to deal with a lot (checking for self-assignment), and I'd have expected the NumPy folks to have predicted it, since they wrote it (mostly) in C.

Scaevolus
Apr 16, 2007

UberJumper posted:

a. comtypes people get pissy, and can they basically tell me to take it down?

It doesn't really matter. It's distributed under the MIT License, so they can't prevent you from modifying it to work for your particular case.

Stabby McDamage
Dec 11, 2005

Doctor Rope
I'm having to compose regular expressions, and I often need fairly complex subexpressions that i don't want to repeat. I can store them as a string, but then my regex looks like:
code:
re.match(THING1+',\s*'+THING2,s)
This gets confusing as regexs grow large. I'm thinking of making a wrapper function to re.match() that replaces tokens in the regex, so I can do
code:
my_match('THING1,\s*THING2',s)
Is there a better way to do this?

Lurchington
Jan 2, 2003

Forums Dragoon
In the past I've used template strings to do stuff like this.

you could then have the option of making your wrapper something like:

code:
def my_match(regex, s):
   your_subexpression_dict = {"THING1": <your_regex1>, "THING2": <your_regex2>}
   regex_template = Template(regex)
   return re.match(regex_template.safe_substitute(your_subexpression_dict), s)

which would allow you to write your expressions as:

code:
my_match('$THING1,\s*$THING2', s)

UberJumper
May 20, 2007
woop

Scaevolus posted:

It doesn't really matter. It's distributed under the MIT License, so they can't prevent you from modifying it to work for your particular case.

thanks!

Stabby McDamage
Dec 11, 2005

Doctor Rope

Lurchington posted:

In the past I've used template strings to do stuff like this.

you could then have the option of making your wrapper something like:

code:
def my_match(regex, s):
   your_subexpression_dict = {"THING1": <your_regex1>, "THING2": <your_regex2>}
   regex_template = Template(regex)
   return re.match(regex_template.safe_substitute(your_subexpression_dict), s)

which would allow you to write your expressions as:

code:
my_match('$THING1,\s*$THING2', s)

If I find myself adding more substitutions, I'll add this in. Thanks!

tripwire
Nov 19, 2004

        ghost flow

UberJumper posted:

thanks!

When you're done, email the developers of comtypes and laugh at them for being completely retarded. It takes a special kind of stupid to use a BSD/MIT license and then tell people they can't modify your code.

Thermopyle
Jul 1, 2003

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

Concise method of creating a new list from every nth item of a list?

I seem to write multiple lines of code for this and it seems kinda ridiculous.

Example:

Every 3rd item from list a makes list b.

a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [3, 6, 9]

UberJumper
May 20, 2007
woop

Thermopyle posted:

Concise method of creating a new list from every nth item of a list?

I seem to write multiple lines of code for this and it seems kinda ridiculous.

Example:

Every 3rd item from list a makes list b.

a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [3, 6, 9]

b = [x for x in a[::3]]

A A 2 3 5 8 K
Nov 24, 2003
Illiteracy... what does that word even mean?

UberJumper posted:

b = [x for x in a[::3]]

Any reason not to do b = a[::3]?

a[2::3] actually gives [3,6,9]

Thermopyle
Jul 1, 2003

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

I was not aware of that syntax with slicing. Thanks guys.

Another question:

alist = ['a', 'b', 'c', 'd', 'e', 'f']

Given an index, let's say 2, what's a concise, yet readable, way to create a list that begins with alist[3] and wraps around to alist[2], so I end up with:

blist = ['d', 'e', 'f', 'a', 'b', 'c']

king_kilr
May 25, 2007

Thermopyle posted:

I was not aware of that syntax with slicing. Thanks guys.

Another question:

alist = ['a', 'b', 'c', 'd', 'e', 'f']

Given an index, let's say 2, what's a concise, yet readable, way to create a list that begins with alist[3] and wraps around to alist[2], so I end up with:

blist = ['d', 'e', 'f', 'a', 'b', 'c']

blist = alist[idx:] + alist[:idx]

A A 2 3 5 8 K
Nov 24, 2003
Illiteracy... what does that word even mean?

Thermopyle posted:

alist = ['a', 'b', 'c', 'd', 'e', 'f']

Given an index, let's say 2, what's a concise, yet readable, way to create a list that begins with alist[3] and wraps around to alist[2], so I end up with:

blist = ['d', 'e', 'f', 'a', 'b', 'c']

>>> alist[3:] + alist[0:3]
['d', 'e', 'f', 'a', 'b', 'c']

Thermopyle
Jul 1, 2003

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

king_kilr posted:

blist = alist[idx:] + alist[:idx]

God, I'm an idiot. I think I've stayed up too late.

Captain Capacitor
Jan 21, 2008

The code you say?

Thermopyle posted:

God, I'm an idiot. I think I've stayed up too late.

Don't feel too bad. List comprehensions slices are powerful and mysterious creatures something. They're a feature I miss quite a bit when switching to other languages.

Edit: I'm just going to quite posting altogether :/

Captain Capacitor fucked around with this message at 23:20 on Apr 9, 2010

king_kilr
May 25, 2007

Captain Capacitor posted:

Don't feel too bad. List comprehensions are powerful and mysterious creatures. They're a feature I miss quite a bit when switching to other languages.

What? Those are list comprehensions, just slicing.

AbsentMindedWelder
Mar 26, 2003

It must be the fumes.
I now decided to try interfacing a 2x16 Character LCD module to my parallel port. This is my first program dealing with ASCII to binary conversion, in addition to accepting command line arguments.

Any newbish mistakes I should know about?

code:
#!/usr/bin/python
# Filename: lcd3.py
import parallel
import time
import binascii
import sys

p = parallel.Parallel() # Intializes parallel port
p.setSelect(1) # "Select", pin17 LPT; "E" pin6 LCD; Normally 1.  When 0, LCD will read data

def sendLCDcommand(LCDdata):
    p.setInitOut(0) # "Init", pin16 LPT; "RS' pin4 LCD; 1 = LCD Character entry mode, 0 = LCD Command entry mode.
    p.setData(int(str(LCDdata), 16)) # Converts LCDdata from string to hex, sends to parallel port data lines.
    p.setSelect(0) # "Select", pin17 LPT; "E" pin6 LCD; Normally 1.  When 0, LCD will read data.
    p.setSelect(1) # "Select", pin17 LPT; "E" pin6 LCD; Normally 1.  When 0, LCD will read data.

def sendLCDchar(character):
    p.setInitOut(1) # "Init", pin16 LPT; "RS' pin4 LCD; 1 = LCD Character entry mode, 0 = LCD Command entry mode.
    LCDdata = binascii.b2a_hex(character) # Converts ASCII string to hexadecimal string.
    p.setData(int(str(LCDdata), 16)) # Converts LCDdata from string to hex, sends to parallel port data lines.
    p.setSelect(0) # "Select", pin17 LPT; "E" pin6 LCD; Normally 1.  When 0, LCD will read data.
    p.setSelect(1) # "Select", pin17 LPT; "E" pin6 LCD; Normally 1.  When 0, LCD will read data.
    
if len(sys.argv) < 3:
    print 'Too few arguments given. Please supply 2 strings, in quotes, 16 characters or less.'
    exit()

if len(sys.argv) > 3:
    print 'Too many arguments given. Please supply 2 strings, in quotes, 16 characters or less.'
    exit()

line1 = sys.argv[1]
line2 = sys.argv[2]

if len(line1) > 16:
    print 'Line 1 must be 16 characters or less. You supplied', len(line1), 'characters.'
    exit()

if len(line2) > 16:
    print 'Line 2 must be 16 characters or less. You supplied', len(line2), 'characters.'
    exit()

sendLCDcommand('0f') # Enables LCD: to accept data
sendLCDcommand('38') # Enables LCD: second line, 5x7 format, 8 bit data
sendLCDcommand('01') # Clears Display
time.sleep(.05) # Pause to allow LCD time to clear display

for LCDdata in list(line1):
    sendLCDchar(LCDdata) 

sendLCDcommand('c0') # Moves cursor to first position on line 2

for LCDdata in list(line2):
    sendLCDchar(LCDdata)
    
exit()

Stabby McDamage
Dec 11, 2005

Doctor Rope

dv6speed posted:

I now decided to try interfacing a 2x16 Character LCD module to my parallel port. This is my first program dealing with ASCII to binary conversion, in addition to accepting command line arguments.

Any newbish mistakes I should know about?

I think you're overcomplicating things a bit. You don't need hex-to-binary conversion for anything you're doing, and if you did, you don't need the binascii module to achieve it. This should be equivalent to what you had:
code:
#!/usr/bin/python
# Filename: lcd3.py
import parallel
import time
import sys

p = parallel.Parallel() # Intializes parallel port
p.setSelect(1) # "Select", pin17 LPT; "E" pin6 LCD; Normally 1.  When 0, LCD will read data

def sendLCDbyte(byte,init_pin=1):
    if (type(byte)==str): 
        byte=ord(byte) # convert string to integer if needed
    p.setInitOut(init_pin) # "Init", pin16 LPT; "RS' pin4 LCD; 1 = LCD Character entry mode, 0 = LCD Command entry mode.
    p.setData(byte) # Writes byte to the data pins
    p.setSelect(0) # "Select", pin17 LPT; "E" pin6 LCD; Normally 1.  When 0, LCD will read data.
    p.setSelect(1) # "Select", pin17 LPT; "E" pin6 LCD; Normally 1.  When 0, LCD will read data.
    
def sendLCDcommand(byte): sendLCDbyte(byte,init_pin=0) 

def sendLCDstring(string,init_pin=1):
    for char in string: 
        sendLCDbyte(char,init_pin)

if len(sys.argv) != 3 or len(sys.argv[1])>16 or len(sys.argv[2])>16:
    print 'Please supply 2 strings, in quotes, 16 characters or less.'
    sys.exit(1)

line1 = sys.argv[1]
line2 = sys.argv[2]

sendLCDcommand(0x0f) # Enables LCD: to accept data
sendLCDcommand(0x38) # Enables LCD: second line, 5x7 format, 8 bit data
sendLCDcommand(0x01) # Clears Display

time.sleep(0.05) # Pause to allow LCD time to clear display

sendLCDstring(line1)

sendLCDcommand(0xc0) # Moves cursor to first position on line 2

sendLCDstring(line2)
Now, sendLCDbyte works with either a single-character string or an integer. For your commands, you can specify hex integers directly -- no need to convert from hex strings. Even if you did need to do hex conversion somewhere, that's built into python strings:
code:
>>> '35'.decode('hex')
'5'
>>> 'cat'.encode('hex')
'636174'

AbsentMindedWelder
Mar 26, 2003

It must be the fumes.

Stabby McDamage posted:

:words:

Awesome stuff, thanks!

RobotEmpire
Dec 8, 2007
I'm following along with the MIT Open CourseWare lectures on Python (they're great btw). I'm doing the first quiz now.

One thing I've learned in the few cumulative weeks in my life I've spent doing Python is that just because it works doesn't mean it's most efficient. One of the problems on the quiz was to print the first n odd perfect squares. The below works (wrote it myself... /flex)... Can anyone point out some general things to optimize it? (Not looking for the code itself... just hints maybe?)

code:
import math

def first_N(n):
    assert n >= 0, 'n must be a positive integer'
    ctr = 1
    perf_squares = []
    while len(perf_squares) < n:
        square = math.sqrt(ctr)
        if square == int(square):
            perf_squares.append(ctr)
            #print len(perf_squares)
            ctr += 2
        else:
            ctr += 2
            #print len(perf_squares)
    return perf_squares

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
code:
def first_N(n):
    assert n >= 0, 'n must be a positive integer'
    return [i**2 for i in xrange(1, 2*n, 2)]
A perfect square is odd iff its square root is odd. (I'd give hints but it's a one-liner so it's hard to hint at, really.)

EDIT: here's how you do it without list comprehensions:
code:
def first_N(n):
    assert n >= 0, 'n must be a positive integer'
    perf_squares = []
    for i in xrange(1, 2*n, 2):
        perf_squares.append(i**2)
    return perf_squares

Avenging Dentist fucked around with this message at 05:51 on Apr 10, 2010

RobotEmpire
Dec 8, 2007

Avenging Dentist posted:

code:
def first_N(n):
    assert n >= 0, 'n must be a positive integer'
    return [i**2 for i in xrange(1, 2*n, 2)]
A perfect square is odd iff its square root is odd. (I'd give hints but it's a one-liner so it's hard to hint at, really.)

EDIT: here's how you do it without list comprehensions:
code:
def first_N(n):
    assert n >= 0, 'n must be a positive integer'
    perf_squares = []
    for i in xrange(1, 2*n, 2):
        perf_squares.append(i**2)
    return perf_squares

drat, ok that's cool. I see what you did, there. Thanks. :science:

Captain Capacitor
Jan 21, 2008

The code you say?

dv6speed posted:

Awesome stuff, thanks!

Just a little awesome tidbit, I use a project called cmdln to create interactive and non-interactive shells. You could use it to create a live shell to test sending messages to the LCD. It's basically a souped-up optparse setup.

devilmouse
Mar 26, 2004

It's just like real life.
Google is failing me (or rather, it's just cluttered up with old old no longer maintained code). Anyone know a serviceable package for editing video files in Python? There was a promising looking thing called DVEdit, but it's nowhere to be found. PyMedia hasn't been touched since '06.

I'm looking to open up some AVI files, copy some audio/video from certain timeslices into a new file and mix in some audio over it. Just some really primitive video-editing.

Pyglet is a possibility, but the A/V support seems pretty limited from a brief look.

Am I missing some sweet secret media package?

RobotEmpire
Dec 8, 2007

Avenging Dentist posted:

code:
def first_N(n):
    assert n >= 0, 'n must be a positive integer'
    return [i**2 for i in xrange(1, 2*n, 2)]
A perfect square is odd iff its square root is odd.

I appreciate this example even more now. It showed me how list comprehensions worked better than the docs did. One of the other assignments was to write a script to find the nth prime.

code:
def dosieve(poss_prime):
    start = range(2,poss_prime**0.5+1)
    if all([poss_prime%i for i in start]): 
        return poss_prime
    #nums = []
    #for i in start:
        #nums.append(poss_prime%i)
    #if all(nums):
        #return poss_prime
    
All the stuff commented out is what I had until this evening. I love list comprehensions :3:

Scaevolus
Apr 16, 2007

RobotEmpire posted:

You probably want to use xrange instead of range when possible.

Try giving your functions more descriptive names (and a few optimizations)
code:
def is_prime(n):
    if n % 2 and all(n % i for i in xrange(3, int(n ** 0.5) + 1, 2)): 
        return True
    if n == 2:
        return True
    return False

print filter(is_prime, xrange(2, 1000))
Generator expressions are very similar to list comprehensions, but they are more efficient because they don't make require an intermediate list.

This uses a list comprehension:
code:
for x in [n ** 2 for n in range(1000)]:
    pass
The above will create two lists: one like [0, 1, 2, ... 999], and one like [0, 1, 4, 9, ... 998001]. Creating lists is very fast for small sizes, but as they increase (millions or billions of elements), you can really feel the speed difference.


This uses a generator expression:
code:
for x in (n ** 2 for n in xrange(1000)):
    pass
The above will create two iterators-- objects that yield values every time next() is called on them-- that don't store every value like the lists do, just the values that are necessary for the moment.

xrange() returns an iterator. range returns a list.

Scaevolus fucked around with this message at 08:14 on Apr 11, 2010

mystes
May 31, 2006

devilmouse posted:

Google is failing me (or rather, it's just cluttered up with old old no longer maintained code). Anyone know a serviceable package for editing video files in Python? There was a promising looking thing called DVEdit, but it's nowhere to be found. PyMedia hasn't been touched since '06.

I'm looking to open up some AVI files, copy some audio/video from certain timeslices into a new file and mix in some audio over it. Just some really primitive video-editing.

Pyglet is a possibility, but the A/V support seems pretty limited from a brief look.

Am I missing some sweet secret media package?
The python bindings for gstreamer may be your best bet. It's too bad there isn't any good up-to-date ffmpeg module since that was my first thought too.

mystes fucked around with this message at 15:10 on Apr 11, 2010

RobotEmpire
Dec 8, 2007

Scaevolus posted:

This uses a generator expression:
code:
for x in (n ** 2 for n in xrange(1000)):
    pass
The above will create two iterators-- objects that yield values every time next() is called on them-- that don't store every value like the lists do, just the values that are necessary for the moment.

xrange() returns an iterator. range returns a list.

So I assume a generator expression creates a tuple vice a list? Or are the outer parens for grouping?

Stabby McDamage
Dec 11, 2005

Doctor Rope

Scaevolus posted:

This uses a generator expression:
code:
for x in (n ** 2 for n in xrange(1000)):
    pass

Wait, so if you take a list comprehension, make sure all its component parts are generators, and replace the brackets with parens, then the whole thing is also a generator?

nbv4
Aug 21, 2002

by Duchess Gummybuns

RobotEmpire posted:

So I assume a generator expression creates a tuple vice a list? Or are the outer parens for grouping?

They're for grouping. It works just the same as how a generator would work, so no tuples are made. All though, I think that syntax is 2.6/3.x only.

devilmouse
Mar 26, 2004

It's just like real life.

mystes posted:

The python bindings for gstreamer may be your best bet. It's too bad there isn't any good up-to-date ffmpeg module since that was my first thought too.

Yeah, looks like this is gonna have to do. It's too bad about that DVEdit package, it really looked like the tits too.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

RobotEmpire posted:

So I assume a generator expression creates a tuple vice a list? Or are the outer parens for grouping?

This is really important: an expression inside parens but without commas (commas inside other parens don't count) aren't tuples. You have to type (foo,) for a one-element tuple. Also function calls aren't tuples either.

Lonely Wolf
Jan 20, 2003

Will hawk false idols for heaps and heaps of dough.

nbv4 posted:

All though, I think that syntax is 2.6/3.x only.

2.5+, I believe

Allie
Jan 17, 2004

Generator comprehensions were added in 2.4.

RobotEmpire
Dec 8, 2007

Avenging Dentist posted:

This is really important: an expression inside parens but without commas (commas inside other parens don't count) aren't tuples. You have to type (foo,) for a one-element tuple. Also function calls aren't tuples either.

Buh! I knew this. Thanks for the reminder.

As I get deeper into this MIT Computer Science 6.00 introduction to computational thinking course I realize how crappy my math instruction was when I was in high school... 12 years ago.

edit: On the other hand, I feel like I learn something important every loving lecture. I just got a brain dump about linear/log/exp/quad algorithms... and I actually understood the concepts by the end.

RobotEmpire fucked around with this message at 19:40 on Apr 11, 2010

LuckySevens
Feb 16, 2004

fear not failure, fear only the limitations of our dreams

Stupid python question, I'm sorting a 2x20 list with a string and a % integer, and I want to sort by the absolute value and put the highest 5 entries into a list. I suck at this but this is what I came up with:

code:
def bigmovers():
    list = __request('ST')
    change = []
    for m in list:
        change.append([m[2], m[20]])
    sorted(change, key=lambda stocks: stocks[1])
    return change
Now this sorts by value, negative and positive, but not absolute value. It won't let me just add abs(stocks[1]) to the lambda like I thought it might in my head, obviously for a good reason. Any ideas?

A A 2 3 5 8 K
Nov 24, 2003
Illiteracy... what does that word even mean?

LuckySevens posted:

Stupid python question, I'm sorting a 2x20 list with a string and a % integer, and I want to sort by the absolute value and put the highest 5 entries into a list. I suck at this but this is what I came up with:

code:
def bigmovers():
    list = __request('ST')
    change = []
    for m in list:
        change.append([m[2], m[20]])
    sorted(change, key=lambda stocks: stocks[1])
    return change
Now this sorts by value, negative and positive, but not absolute value. It won't let me just add abs(stocks[1]) to the lambda like I thought it might in my head, obviously for a good reason. Any ideas?

That should work:

>>> l = [['',5],['',-2],['',2],['',1]]
>>> sorted(l, key=lambda x: abs(x[1]))
[['', 1], ['', -2], ['', 2], ['', 5]]

Adbot
ADBOT LOVES YOU

LuckySevens
Feb 16, 2004

fear not failure, fear only the limitations of our dreams

ah, i think its screwing up because my values have % symbols, ill just parse those. duh :P

  • Locked thread