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
No Safe Word
Feb 26, 2005

Bonus posted:

Here's a cool thing I've just found out while doing some stuff for school. The zip function works as its own inverse.
Hah, I literally just did something with this 2 days ago. I was goofing off writing some genetic algorithms stuff in Python and I was doing the whole "roulette choice" algorithm (where each item in a population has a "fitness score" and you choose a random item in the population such that the more fit an item in the population is, it has a proportionally higher chance of being chosen), so I had to do something like this:

code:
# we have fitness_list [2, 5, 10, ...], and population ['foo', 'bar', 'baz', ...]
# which are commonly indexed (ie, the fitness of population[0] is fitness_list[0],
# and we want those same two lists back, but sorted in order of most fit to least
fit_pop = zip(fitness_list, population)
# y first because we want it in descending order
fit_pop.sort(lambda x,y: cmp(y[0], x[0])
fitness_list, population = zip(*fit_pop)
Fairly sure that there are better ways of doing the rest of it, and make it so that I wouldn't need this type of logic anyway, but I found the same thing that you did and thought it pretty cool too :)

Adbot
ADBOT LOVES YOU

Alan Greenspan
Jun 17, 2001

Hey guys, I could need a short example script for one of my projects. It's a Java program that uses Jython for scripting support.

Here's what I have. There's this function convert(data, offset, size) where data is a byte array, offset is a position inside the byte array, and size is a number of bytes. Starting at position offset, the function takes size bytes from the data array and converts it into a string that looks like a MASM (Microsoft Assembler) array.

Example Output:

myArray db 030h, 0F0h, 000h, 057h, ...

Note that each data line should have at max 10 entries, then I want a line break into the next line.

Here's what I have so far.

code:
def convert(self, data, offset, size):
    return ', '.join([ '0%02Xh' % (c & 0xFF) for c in (list(data))[offset:offset + size]])
This returns the entire array in one huge line. Is there a cute way to add the line breaks? Nothing matters but shortness of the source code. Is there a way to make the code I wrote shorter? Is there a short way to get rid of the leading 0 for values between 00 and 9F? MASM requires the leading 0 only for values starting with a character (0xA0 - 0xFF).

inveratulo
May 14, 2002
wat
I'm writing a little script to telnet around to different routers, but unfortunately the routers default to a little user interface (Netopia 3386) when establishing a telnet connection. Pressing ctrl-N drops the telnet window into a command line, but I cannot figure out how to send this control character through python. I've been using telnetlib just for proof of concept, but probably will use pexpect in my final program.

How do I send control characters through either telnetlib or pexpect?

deimos
Nov 30, 2006

Forget it man this bat is whack, it's got poobrain!

inveratulo posted:

How do I send control characters through either telnetlib or pexpect?

Ok, this is a slight case of RTFM, because pexpect has a sendcontrol()

mantaworks
May 6, 2005

by Fragmaster

Alan Greenspan posted:

This returns the entire array in one huge line. Is there a cute way to add the line breaks? Nothing matters but shortness of the source code. Is there a way to make the code I wrote shorter?

Write it in perl.

inveratulo
May 14, 2002
wat

deimos posted:

Ok, this is a slight case of RTFM, because pexpect has a sendcontrol()

hmmm sendcontrol was the first thing I tried actually but I couldn't get it to work. I kept getting an attribute error:
AttributeError: 'spawn' object has no attribute 'sendcontrol'

Should I be creating my connection object differently? This is how I did it:
conn = pexpect.spawn('telnet ' + host)


edit: I had version 2.1 which did not have sendcontrol(). I updated and now it works, thanks! I propose a new acronym: UTFM - Update The loving Modules.

inveratulo fucked around with this message at 18:29 on Mar 15, 2008

deimos
Nov 30, 2006

Forget it man this bat is whack, it's got poobrain!

inveratulo posted:

hmmm sendcontrol was the first thing I tried actually but I couldn't get it to work. I kept getting an attribute error:
AttributeError: 'spawn' object has no attribute 'sendcontrol'

Should I be creating my connection object differently? This is how I did it:
conn = pexpect.spawn('telnet ' + host)

update your pexpect

Moof Strydar
Jul 13, 2001

Alan Greenspan posted:

Is there a short way to get rid of the leading 0 for values between 00 and 9F? MASM requires the leading 0 only for values starting with a character (0xA0 - 0xFF).

You could try the old C-style and-or trick to determine if it needs a leading 0:
code:
(c > 0x99) and '0' or ''
In your code it will look like this (modified so as not to break the tables):
code:
def convert(self, data, offset, size):
  return ', '.join([ ((c > 0x99) and '0' or '') + \
                   '%02Xh' % (c & 0xFF) for c in (list(data))[offset:offset + size]])
You can do something similar for the line breaks too. Here's a spot of code that will print 10 entries on each line:
code:
data = [1, 2, ... ]
out = ''
for i, c in enumerate(data):
    out += str(c) + ', ' + (not (i + 1) % 10 and '\n' or '')
Enumerate will give us the positions of each entry in the list. We can use this to determine every 10th one, via the modulo function (we add 1 to the enumerated value because it starts at 0). You could swap the positions of the '\n' and '' and get rid of the "not" to shorten it a little, I've just done it this way so the intention is a little clearer. Scratch that, there's problems when you use an empty string in an and-or like this. Read Dive Into Python (which I'm cribbing from) to find out why. There's a workaround but it's not exactly obvious stuff and will make your code harder to read.

In your code (with the earlier addition) it will look something like this (also non-table breaking):
code:
def convert(self, data, offset, size):
  return ', '.join([ ((c > 0x99) and '0' or '') + \
                     '%02Xh' % (c & 0xFF) + \
                     (not (i + 1) % 10 and '\n' or '') for \
                     i, c in enumerate((list(data))[offset:offset + size]]))
As for making it shorter...

:shobon:

EDIT: Actually, just tried it, this doesn't seem to work properly with the join function, it will have a leading ', ' at the start of each new line. Bum!

EDIT 2: Oh, easy workaround, just move the insertion of a newline to the start, and trigger for the item after every tenth item. Uh, that's not very clear, but here's what I mean:
code:
def convert(self, data, offset, size):
  return ', '.join([ (not i % 10 and '\n' or '') + \ # newline every 10th
                     ((c > 0x99) and '0' or '') + \  # leading '0'
                     '%02Xh' % (c & 0xFF) for \      # actual number
                     i, c in enumerate((list(data))[offset:offset + size]]))
Unfortunately it will add a newline at the very start as well. Oh well.

Moof Strydar fucked around with this message at 21:21 on Mar 17, 2008

Allie
Jan 17, 2004

Just FYI, you don't need those line continuation characters as new lines and whitespace have no significance inside parentheses (or brackets, or braces).

bitprophet
Jul 22, 2004
Taco Defender

Moof Strydar posted:

code:
(c > 0x99) and '0' or ''

Just want to pop in with the usual "be really careful with this tactic" warning, it's really easy to make a stupid mistake like the following:

code:
(c <= 0x99) and '' or '0'
Which would appear to be equivalent to the quoted example, but isn't, because it will always return '0' (because "<anything> and ''" will always evaluate to False due to the empty string).

ashgromnies
Jun 19, 2004
EDIT: Figured it out, giving a uri like "twitter.com" to the HTTPPasswordMgr.add_password method instead of the full path to what I was trying to access works.

edit2 ahh, more urllib2 questions... I wrote a basic class:

code:
#!/usr/bin/python
import urllib2
class Twitter:
    "Twitter API class"

    def __init__(self):
        self.protocol = 'http://'
        username = 'myuser'
        password = 'mypass'
        realm = "Twitter API"

        passman = urllib2.HTTPPasswordMgr()
        passman.add_password(realm, 'twitter.com', username, password)

        authhandler = urllib2.HTTPBasicAuthHandler(passman)

        opener = urllib2.build_opener(authhandler)

        urllib2.install_opener(opener)

    def urlopen(self, url):
        print "opening "+self.protocol+url
        return urllib2.urlopen(self.protocol + url)

    def try_auth(self):
        theurl = 'twitter.com/account/verify_credentials.xml'
        pagehandle = self.urlopen(theurl)
        return pagehandle.read()

    def get_user_timeline(self,format):
        theurl = 'twitter.com/statuses/user_timeline.' + format
        pagehandle = self.urlopen(theurl)
        return pagehandle.read()
What's weird is that calling try_auth() works and authenticates, but get_user_timeline('atom') doesn't.

code:
>>> from twitter import Twitter
>>> twit = Twitter()
>>> twit.try_auth()
opening http://twitter.com/account/verify_credentials.xml
'<authorized>true</authorized>'
>>> twit.get_user_timeline('atom')
opening http://twitter.com/statuses/user_timeline.atom
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "twitter.py", line 32, in get_user_timeline
    pagehandle = self.urlopen(theurl)
  File "twitter.py", line 23, in urlopen
    return urllib2.urlopen(self.protocol + url)
  File "/usr/local/lib/python2.5/urllib2.py", line 121, in urlopen
    return _opener.open(url, data)
  File "/usr/local/lib/python2.5/urllib2.py", line 380, in open
    response = meth(req, response)
  File "/usr/local/lib/python2.5/urllib2.py", line 491, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/local/lib/python2.5/urllib2.py", line 418, in error
    return self._call_chain(*args)
  File "/usr/local/lib/python2.5/urllib2.py", line 353, in _call_chain
    result = func(*args)
  File "/usr/local/lib/python2.5/urllib2.py", line 499, in http_error_default
    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 406: Not Acceptable

However, this does work:
code:
#!/usr/bin/python
import urllib2
import base64

base64string = base64.encodestring('%s:%s' % ('myuser','mypass'))[:-1]

twitturl = 'http://twitter.com/statuses/user_timeline.atom'
req = urllib2.Request(twitturl)
req.add_header("Authorization", "Basic %s" % base64string)
try:
    handle = urllib2.urlopen(req)
except IOError, e:
    if hasattr(e, 'code'):
        if e.code != 401:
            print 'We got another error'
            print e.code
        else:
            print e.headers
            print e.headers['www-authenticate']
print handle.read()
Obviously I'm doing something wrong with the authentication but I can't figure out what.

edit: ah, some cat at google already wrote a python twitter api... but I wanted to write my own. http://code.google.com/p/python-twitter/

editx3: hooray, got it working by doing what he did in his example and I did in my second code sample and added the Basic auth header as well.

ashgromnies fucked around with this message at 19:24 on Mar 17, 2008

Moof Strydar
Jul 13, 2001

Milde posted:

Just FYI, you don't need those line continuation characters as new lines and whitespace have no significance inside parentheses (or brackets, or braces).

Not only that, they'll actually cause errors in the last example, because you can't have comments after them!

Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.

Moof Strydar posted:

code:
(c > 0x99) and '0' or ''

code:
'' if c > 0x99 else '0'
v:shobon:v

hey mom its 420
May 12, 2007

Habnabit posted:

code:
'' if c > 0x99 else '0'
v:shobon:v

Yeah, that is the prefered usage but I don't think Jython supports that yet.

Does anyone know if they'll be changing yield to a function in Py3k? It seems kind of silly not to, because they're already changing print to a function and now yield can give you a return value so writing foo = (yield value) instead of foo = yield(value) just seems kind of hackish and like it doesn't go along with the rest of Python.

Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.

Bonus posted:

Does anyone know if they'll be changing yield to a function in Py3k? It seems kind of silly not to, because they're already changing print to a function and now yield can give you a return value so writing foo = (yield value) instead of foo = yield(value) just seems kind of hackish and like it doesn't go along with the rest of Python.

It appears so.
code:
Python 3.0a3 (r30a3:61158, Mar  1 2008, 22:22:46)
[GCC 4.0.1 (Apple Computer, Inc. build 5363)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def f():
...     x = 1
...     while x:
...             x = (yield x) + 1
...
>>>
>>> def f():
...     x = 1
...     while x:
...             x = yield(x) + 1
...
>>>

Contract Otter
May 31, 2007
I've been fumbling around with Python the last couple of days and studying various tutorials for Python itself and libraries such as pygame. However, I'm quite unexperienced in coding and with only a minor Java background I find it pretty hard to really learn and apply my learnings in practice without doing "homework assignments".

It would really help my learning if I'd be able to program and think for myself given problems that I know can be done with the skills I've learned so far. Are there that kind of tutorials available? For example a university course with open material or something.

Alan Greenspan
Jun 17, 2001

Moof Strydar posted:

code:
def convert(self, data, offset, size):
  return ', '.join([ (not i % 10 and '\n' or '') + \ # newline every 10th
                     ((c > 0x99) and '0' or '') + \  # leading '0'
                     '%02Xh' % (c & 0xFF) for \      # actual number
                     i, c in enumerate((list(data))[offset:offset + size]]))
Unfortunately it will add a newline at the very start as well. Oh well.

Thanks man, that's really sweet. I managed to find another solution with a helper function.

code:

def splitCount(seq, length):
	return [seq[i:i+length] for i in range(0, len(seq), length)]

def convert(self, data, offset, size):
	return 'buffer db \n\t' + '\n\t'.join( \
        splitCount(', '.join([ '0%02Xh' % (c & 0xFF) for c in (list(data))[offset:offset + size]]), 60))
I think I'm gonna use your code though. One-liners are cuter. :)

hey mom its 420
May 12, 2007

If you make helper functions just so they're used once, you can always cram them in a lambda if you want stuff in one line. So your example can become:
code:
def convert(self, data, offset, size):
	return 'buffer db \n\t' + '\n\t'.join( \
        (lambda seq, length:[seq[i:i+length] for i in range(0, len(seq), length)]) \
        (', '.join([ '0%02Xh' % (c & 0xFF) for c in (list(data))[offset:offset + size]]), 60))

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
Ick, no. Make it easier to read! I'm in favour of more helper functions. Remember you can nest them.

code:
def convert(self, data, offset, size):

    def splitCount(seq, length):
        return [seq[i:i+length] for i in range(0, len(seq), length)]

    def formatHex(c):
        return '0%02Xh' % (c & 0xFF)

    dataList = list(data)[offset:offset + size]
    lines = splitCount(', '.join([formatHex(c) for c in dataList]), 60)
    return 'buffer db \n\t' + '\n\t'.join(lines)
Wow, it's a couple of lines longer, how terrible. But I can actually tell what it does without spending 20 minutes puzzling it out!

hey mom its 420
May 12, 2007

Yeah, I'm all for readability and I'd suggest going that way too. It's the most important characteristic of code, apart from elegance. Make the code so people can read it first, then for computers.

But he mentioned that he wants the code to be as short as possible, so that's why I posted that solution. Although that presents the question, why would anyone want shortness of code over readability, apart from maybe limited storage space, but I doubt that's the issue..

Alan Greenspan
Jun 17, 2001

The reason for why I need it shorter is unbelievably silly. I work in a small, very specialized part of the industry where people know each other quite well. So when I post a readable 10-liner on my blog that shows an example of what you can do using our software/library it's very likely that some guy from the competition chimes in and posts an unreadable 1-liner that does the same in their software/library. Playing code golf with the plugin support of our products is just a way to amuse ourselves.

I have real, readable examples for the software/library too, but this is the one-liner to one-up the competition. :angel:

Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.

JoeNotCharles posted:

code:
def convert(self, data, offset, size):

    def splitCount(seq, length):
        return [seq[i:i+length] for i in range(0, len(seq), length)]

    def formatHex(c):
        return '0%02Xh' % (c & 0xFF)

    dataList = list(data)[offset:offset + size]
    lines = splitCount(', '.join([formatHex(c) for c in dataList]), 60)
    return 'buffer db \n\t' + '\n\t'.join(lines)

One thing about this: defining the functions nested like that is actually a performance penalty in this case because neither function use any of the local variables in the parent function directly. Every time the code is run, the functions are regenerated.

hey mom its 420
May 12, 2007

Ech. Performance, schmerformance!

do it
Jan 3, 2006

don't tell me words don't matter!

Contract Otter posted:

I've been fumbling around with Python the last couple of days and studying various tutorials for Python itself and libraries such as pygame. However, I'm quite unexperienced in coding and with only a minor Java background I find it pretty hard to really learn and apply my learnings in practice without doing "homework assignments".

It would really help my learning if I'd be able to program and think for myself given problems that I know can be done with the skills I've learned so far. Are there that kind of tutorials available? For example a university course with open material or something.
This might be too basic for what you're looking for, but Learning Python has exercises at the end of each chapter.

Contract Otter
May 31, 2007

do it posted:

This might be too basic for what you're looking for, but Learning Python has exercises at the end of each chapter.

Thanks, I'll look into it!

Acer Pilot
Feb 17, 2007
put the 'the' in therapist

:dukedog:

How do I convert a 4bit binary number to a decimal without using anything like character strings or anything like int("10111", 2)?

I never learned how to do it manually :(

e: this is a "so I know how to do it in the future" type of question!

npe
Oct 15, 2004
Edit: I assume when you say "never learned how to do it manually" you were wondering how to do that, but maybe I misread. Well, here's how to do it manually I guess...

Simple way is to just add the values of the columns set to 1. Like:

code:
 8 4 2 1
---------
 0 0 0 0 = 0
 0 0 0 1 = 1
 0 0 1 0 = 2
 0 0 1 1 = 2 + 1 = 3
 ...
 0 1 0 1 = 4 + 1 = 5
 0 1 1 0 = 4 + 2 = 6
 0 1 1 1 = 4 + 2 + 1 = 7
 ...
 1 1 1 1 = 8 + 4 + 2 + 1 = 15

For 8 bits, same deal, but

code:
 128 64 32 16  8  4  2  1
--------------------------
   1  1  1  1  1  1  1  1 = 255

npe fucked around with this message at 03:15 on Apr 3, 2008

mantaworks
May 6, 2005

by Fragmaster

drcru posted:

How do I convert a 4bit binary number to a decimal without using anything like character strings or anything like int("10111", 2)?

I never learned how to do it manually :(

e: this is a "so I know how to do it in the future" type of question!

Binary isn't really a format like a string or an int. Your binary is represented by one of the built-in types such as an array of strings or a long or whatever. The conversion from <random type> to int is different for every <random type>.

(there is a possibility that the language du jour has a special binary type, then again there will be a built-in function to go from binary to decimal)

edit: wait did I read the question wrong; do you want an explanation of the logic behind the conversion from binary to decimal? Google is better equipped to handle that question. (edit2: and yaoi prophet too ;) )

Destroyenator
Dec 27, 2004

Don't ask me lady, I live in beer

drcru posted:

How do I convert a 4bit binary number to a decimal without using anything like character strings or anything like int("10111", 2)?

code:
a = 10111
sum = count = 0

while a is not 0:
    sum += (a & 1) * 2 ** count
    a /= 10
    count += 1

sum == 23
edit: wow that was quick
But to reiterate, why do you want to do this?

No Safe Word
Feb 26, 2005

Destroyenator posted:

code:
while a is not 0:
Don't do this. You want !=. Yes, it will work for this case, but in general when comparing a variable and a constant number you want the equality test, not the identity test.

The reason it works for this case is that the python interpreter pre-allocates objects for the first 256 or so small integers as singletons.

Fake edit:
code:
>>> a = 0
>>> i = 0
>>> while a is i:
...     a += 1
...     i += 1
...
>>> a
257
>>> i
257
>>> a is i
False

Acer Pilot
Feb 17, 2007
put the 'the' in therapist

:dukedog:

Thanks for the quick replies! The reason I want to know this is because it will likely end up on one of my exams and since they never specified how to convert the numbers in our assignments... I just used the easiest/quickest way :doh:

One more question:
If I get a string like "1234" how do I use division to substring them?

I did something like this instead:
code:
for x in range(0, len(num)):
   print (str(num)[x])

Destroyenator
Dec 27, 2004

Don't ask me lady, I live in beer

No Safe Word posted:

Don't do this. You want !=. Yes, it will work for this case, but in general when comparing a variable and a constant number you want the equality test, not the identity test.

The reason it works for this case is that the python interpreter pre-allocates objects for the first 256 or so small integers as singletons.
Thanks for the heads up, I knew the difference for objects but I thought that integers were a special case (mostly from observing this kind of behaviour).

hey mom its 420
May 12, 2007

I don't know if you're allowed to use it, but you can do this:
code:
>>> a = 11010 #binary equivalent to 26
>>> int(str(a), 2) #the second argument is the base
26
Also what do you mean use division to substring them? Can you provide an example of your desired result on a certain string?

Acer Pilot
Feb 17, 2007
put the 'the' in therapist

:dukedog:

Bonus posted:

I don't know if you're allowed to use it, but you can do this:
code:
>>> a = 11010 #binary equivalent to 26
>>> int(str(a), 2) #the second argument is the base
26
Also what do you mean use division to substring them? Can you provide an example of your desired result on a certain string?

I was using the int(string, base) too :D but yeah, I don't know if it's actually allowed.

As for the division by substring (I'm not sure if that's the proper term) but basically, I think we were supposed to do something like charAt on a string of numbers.

eg. 9765 should print out 9, 7, 6, and 5 individually.

hey mom its 420
May 12, 2007

Aha, well if you're doing that with a string, you can do it like this.
code:
>>> st = "9876"
>>> print ', '.join(st)
9, 8, 7, 6
Or if you have an integer and you want to get the digits without converting it into a string, keep in mind that
code:
>>> 9876 % 10
6

Nevergirls
Jul 4, 2004

It's not right living this way, not letting others know what's true and what's false.

drcru posted:

eg. 9765 should print out 9, 7, 6, and 5 individually.

A string is a sequence, like a list or a tuple, so you can just iterate over it:

code:
>>> s = "boners"
>>> for i in s:
...     print i
... 
b
o
n
e
r
s

tef
May 30, 2004

-> some l-system crap ->
And, of course l=[x for x in "1234"]

Edit: I am a mong, fixed :)

tef fucked around with this message at 16:00 on Apr 3, 2008

hey mom its 420
May 12, 2007

Here's an interesting way to split an integer into digits without converting to strings.
code:
def split_to_digits(n):
  return [n] if n < 10 else split_to_digits(n/10) + [n%10]

hey mom its 420 fucked around with this message at 12:22 on Apr 3, 2008

No Safe Word
Feb 26, 2005

tef posted:

And, of course list=[x for x in "1234"]

And of course not picking variable names that override/shadow builtin functions like list is preferred ;)

Adbot
ADBOT LOVES YOU

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

tef posted:

And, of course l=[x for x in "1234"]

Fixed your variable name for you.

l = list("1234") is easier and clearer.

  • Locked thread