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
hey mom its 420
May 12, 2007

Yeah, I prefer an OOP/functional combination as well. And when I mean OOP, I don't mean Java-style OOP where your program is basically a big inheritance tree, I just mean taking advantage of the fact that everything is an object but avoiding too much inheritance.

Adbot
ADBOT LOVES YOU

hey mom its 420
May 12, 2007

ATLbeer posted:

code:
1> X = 6.
6
2> X = 7.
** exception error: no match of right hand side value 7
Erlang is another planet
Well, first you said X was 6 and then you said it was 7. Are you some kind of liar?

hey mom its 420
May 12, 2007

No need to. Just implement the methods from the interface in those classes and then call them to your heart's content. That's what duck typing is.
For instance, several classes in Python implement the methods from the file class, meaning they can act like files, but they aren't subclasses of any particular class just because of that.
Python 3000 offers abstract base classes but even in Python 3000, I'd still suggest just implementing the methods.

hey mom its 420
May 12, 2007

That's why Python and Ruby rely on automated testing much more than languages with compile-time type safety.

hey mom its 420
May 12, 2007

The Python example your CS prof provided runs in 10.6 seconds on my machine because it creates a lot of intermediate lists in memory only for the purpose of iterating over them. The example is hardly equivalent to the examples in other languages. You can get a nice speed up if you use this code:
code:
is_perfect = lambda x: sum(j for j in xrange(1,x) if x%j == 0) == x
perfect_numbers = (x for x in xrange(1,10000) if is_perfect(x))
for x in perfect_numbers: print x
runs in about 6 seconds for me. So almost a double improvement by using generators.

Anyway, C and Haskell are compiled, while Python is interpreted. You should ask your CS prof what his point is. If his point is that Python is slow or something, that's a pretty weaksauce claim because speed is just one out of many requirements and it has never been a measure of how good a language is on its own. And besides, I'm sure you could make this run quicker if you used Psyco.

hey mom its 420
May 12, 2007

Here's an implementation that uses some recursion and a list comprehension. tails('hey'), for example, produces ['hey','ey','y','']. So it does that and then checks how many elements in that list start with the needle.
code:
def count(sub, s):
    def tails(xs):
        return [] if not xs else [xs] + tails(xs[1:])
    return len([x for x in tails(s) if x.startswith(sub)])
or you could do away with the intermediary tails function and just write it like this:
code:
def count(sub, s):
    starts = 1 if s.startswith(sub) else 0
    return 0 if not s else starts + count(sub, s[1:])
or if you're feeling like a code golfer you can write this out in one line::
code:
def count(sub, s):
    return 0 if not s else (1 if s.startswith(sub) else 0) + count(sub, s[1:])

hey mom its 420 fucked around with this message at 15:22 on Nov 9, 2008

hey mom its 420
May 12, 2007

Because God wants me to. :colbert:
Haha, but still, I don't like using the tricks with and, although I admit, doing s.startswith(sub) + count(sub, s[1:]) is nice, I've been doing Haskell so much that I totally forgot that you can add together booleans and numbers.

hey mom its 420
May 12, 2007

Also, pretty much never do a catch-all except statement. It catches exceptions like the KeyboardInterrupt exception, which you probably want to leave alone. It's good practice to always specify the exceptions that you're catching.

hey mom its 420
May 12, 2007

Yeah but in the case of except: pass, you're implicitly silencing a bunch of exceptions like KeyboardInterrupt and the like.

hey mom its 420
May 12, 2007

Or for even more code shortness and terseness, you can do imap(operator.sub, t1, t2) :v:

hey mom its 420
May 12, 2007

I'm not so hot on music theory, but maybe you could do something like this:
code:
 note_num = {'A':0, 'A#':1, 'Bb':1, 'B':2, 'C':3, 'C#':4, 'Db':4, 'D':5 ... 
So basically a mapping from a note to a numeric value, going up by one on each half-step. For intervals, you just do a mapping of interval name to how many half-steps the interval is.
code:
 interval_num = {'m2':1, 'M2':2, 'm3':3, 'M3':4 ...
To access the list of note names, you do note_num.keys(), same for interval names. Anyway, then if the random chosen note is, say, B and the interval is M2, you do note_num['A#'] to get 1 and interval_num['M2'] to get 2. So then, the user enters 'C', which is the correct value. To check that, you just check if note_num['C'] equals 1 + 2. So basically you'll do
code:
note_num = {'A':0, 'A#':1, 'Bb':1, 'B':2, 'C':3, 'C#':4, 
'Db':4, 'D':5, 'D#':6, 'Eb':6, 'E':7, 'F':8, 'F#':9, 'Gb':9, 'G':10, 'G#':11, 'Ab':11}
interval_num = {'m2':1, 'M2':2, 'm3':3, 'M3':4, '4':5, 'T':6, '5':7, 'm6':8, 'M6':9, 'm7':10, 'M7':11}
Note = random.sample(note_num.keys(), 1)
Interval = random.sample(interval_num.keys(), 1)
NoteString = str(Note).strip('\[\]\'')
IntervalString = str(Interval).strip('\[\]\'')
print 'The Note is ', NoteString
print 'The Interval is ', IntervalString
UserNote = raw_input('Enter the correct ascending interval: ')
if note_num[NoteString] + interval_num[IntervalString] == note_num[UserNote]: 
  print 'Correct!'
else:
  print 'Incorrect!'
But what happens if we get an overflow? Basically if the note is G# and the interval is M2, that nets us a 11 + 2, which is 13, but 13 is not in there. But that comes to an A#, so we obviously have to wrap around, so we do a modulo with 12. So we change the condition to
code:
if (note_num[NoteString] + interval_num[IntervalString])%12 == note_num[UserNote]: 
I haven't tested this, but you probably get the gist of it. Get the numeric value of the note, get the number of half steps for the interval, add those two and see if they respond to the numeric value of the note that the user has entered.
Also I don't think there's much point in putting this into a function, because it doesn't take any parameters or return anything, it just does input and output, so that's better suited to just be in the top level code of the module.

hey mom its 420 fucked around with this message at 04:12 on Dec 21, 2008

hey mom its 420
May 12, 2007

It would, but you'd have to pickle and unpickle it all the time, but sqlite3 is perfect for this kind of stuff.

hey mom its 420
May 12, 2007

Basically sqlite is just a database stored within a single file and you can then run queries on that file and everything. Pretty much one of the best pieces of software around today.

hey mom its 420
May 12, 2007

Why are you storing 40k entries per page?

hey mom its 420
May 12, 2007

I don't see what's wrong with this:
code:
self.genome = [gene + random.gauss(0,1) if random.random() < threshold else gene for gene in self.genome]
if you don't want the gene variable leaking out, you can do
code:
self.genome = list(gene + random.gauss(0,1) if random.random() < threshold else gene for gene in self.genome)
because generator expressions don't leak out variables whereas list comprehensions do, although this is fixed in Py3k.

Also, just doing map(foo, self.genome) won't do a thing because map doesn't modify the list, it just returns a new copy, so you have to do self.genome = map(foo, self.genome)

hey mom its 420 fucked around with this message at 16:39 on Jan 10, 2009

hey mom its 420
May 12, 2007

Why are you iterating with a while and two counters of some sort? Also, you don't have to initialize banwords to a list because it becomes a generator in the next line either way. I'd do
code:
...
banwords = (banword.strip() for banword in openfile.readlines()) #we strip the words for whitespace, which includes \n
...
def on_message(word, word_eol, userdata):
  for banword in banwords:
    if re.search(banword, word[1], re.I):
      xchat.prnt("someone said %s" % banword)
EDIT: What I used there is a generator expression in the first line. If that confuses you, this might be easier to read:
code:
...
banwords = openfile.readlines()
...
def on_message(word, word_eol, userdata):
  for banword in banwords:
    banword = banword.strip()
    if re.search(banword, word[1], re.I):
      xchat.prnt("someone said %s" % banword)
anyway, strip strips whitespace from the left and right and it's best to iterate over stuff with the for ... in construct.

hey mom its 420 fucked around with this message at 22:37 on Feb 8, 2009

hey mom its 420
May 12, 2007

Depends on the script. If you write the script in a portable way, yeah. If not, well, no.
For instance, if you want your code to be more portable, don't hardcode paths and path separators (like blah\blah, because that is blah/blah on unixy systems) but use os.path and so on.
But generally, yes, you can do that. I'd suggest just writing the script first and then posting it here to get people's thoughts on how portable it is.

hey mom its 420
May 12, 2007

Are you sure that's the exact code? This
code:
word = "Hurrah!"
for letter in word:
    print letter
works as expected for me and it's really weird that you're getting problems with this piece of code.

hey mom its 420
May 12, 2007

Maybe he's running it with the perl command, haha.

hey mom its 420
May 12, 2007

This is a good post about it.

hey mom its 420
May 12, 2007

Awesome talk!

hey mom its 420
May 12, 2007

The Haskell solutions use higher-order functions all the time and they're very much different from the C or Java solutions.
Project Euler is good for getting used to the syntax and some basic idioms of a language.
I used Project Euler when learning Haskell and I think it's especially good for learning it because it makes you use infinite lists, higher-order functions, laziness and forces you to think in a functional instead of an imperative manner.
Anyway, I think it's good for getting warmed up with a language. But once you've solved 80 or so problems, it's not about whether you can implement the solution in your programming language of choice, it's about whether you know a mathematical trick or method behind some problem, so that's why I stopped solving them around then.

hey mom its 420
May 12, 2007

That's normal behavior. In order for \ to be interpreted as an actual character instead of an escape sequence, it has to be escaped with, well, \. When you're doing Windows paths in Python, they always look like "C:\\blah\\blah", or you can prefix your string literals with r, then \ isn't treated as an escape sequence, so you can also do r"C:\blah\blah"

hey mom its 420
May 12, 2007

k = [Label(fGrid, text=randice(Dice), font=('Arial Black',80), pady = 10, padx=40).grid(row=x,column=y) for x in range(4) for y in range(4)]

hey mom its 420
May 12, 2007

Yes indeed!

hey mom its 420
May 12, 2007

But he was saving them in the first example, sooo

hey mom its 420
May 12, 2007

Can you post the exact code to reproduce that? My guess is that the items that are in those lists don't have proper __eq__ methods. Cause this works fine:
code:
>>> t = [[1,2,3],[3]]
>>> z = [[1,4,8],[22,3]]
>>> t[0][0] == z[0][0]
True
However, if you do this:
code:
>>> class Foo(object):
...   def __init__(self, bar):
...     self.bar = bar
...
>>> Foo(3) == Foo(3)
False
the answer is False, because those two aren't really the same object, they just have the same properties.

That scoping rule is called shadowing and that's just the way scoping works in Python. I think that if you could modify variables in parent scopes, it would lead to a whole lot of headaches: shadowing makes it so that you capture variables in the parent scope but you can't modify them. It wouldn't be cool if you defined some variable and then called a function only to realize that the function has changed the value of your variable.

hey mom its 420
May 12, 2007

Lamacq posted:

Can you elaborate a little on this, and/or show me where in the python docs I can read up on this syntax? B/c I don't really understand what's going on here.

http://www.python.org/dev/peps/pep-0318/

They're decorators, all they do is take a function and return a function. So doing:
code:
@foo
def bar():
  pass
is equal to doing
code:
def bar():
  pass
bar = foo(bar)

hey mom its 420
May 12, 2007

A basic use of decorators is something like this:
code:
def tell(func):
  def new_func(*args, **kwargs):
    print "I'm being called!"
    ret = func(*args, **kwargs)
    print "I'm finished"
    return ret
  return new_func

@tell
def inc(x):
  return x+1
code:
>>> inc(3)
I'm being called!
I'm finished
4
Now with that in mind, you can use callable objects and some cleverness to do something like this:
code:
class Undoable(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        return self.func(*args, **kwargs)

    def undo(self, func):
        self.undo_action = func
        return func

def do(func):
    return Undoable(func)

@do
def t1(x):
  print "haha"
  return x+1

@t1.undo
def t2():
  print "reversing haha"
It may be a bit confusing at first, but here's how it works: when you do do(func), it will return a callable object that acts exactly like that function, only that it has an extra attribute, namely undo. undo is itself a decorator and when it gets called, it sets the undo_action property of the function to which it belongs to the function that it decorated. So with the above, you can do:
code:
>>> t1(3)
haha
4
>>> t1.undo_action()
reversing haha
But that still doesn't really solve your original problem, which was basically implementing transactions in Python. And that's not a simple task at all, but it's probably doable.

hey mom its 420
May 12, 2007

tripwire posted:

To set the first row:
matrix[0, ] = 0

To set the first column:

matrix[ ,0] = 0

The first seems fine since 0, is (0,), but isn't the second assignment a syntax error?

hey mom its 420
May 12, 2007

Python tries to avoid this kind of stuff because of the whole readability thing and that there should be only one way to write something. I guess you could hack something together by accessing the global dictionary, but blehh.

Adbot
ADBOT LOVES YOU

hey mom its 420
May 12, 2007

Why some people want everything to be a method instead of a plain function I will never understand.

  • Locked thread