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
Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.

ashgromnies posted:

code:
tuple = ()
for i in range(1000000):
    tuple += (i,)
runs slower than

code:
array = []
for i in range(1000000):
    array.append(i)

list.append runs in constant time. In the first case, you're completely rebuilding the tuple every time you're "appending" to it. Tuples aren't lists, and shouldn't be used like lists. As has been mentioned, tuples are immutable and hashable, which means they can be used as dictionary keys and in a myriad of other places where lists can't.

(Also, both run very slow because you're building a list and then iterating over it. The second case is redundant; you can just type 'array = range(1000000)' though, as has been mentioned, it's really a list. If you want to iterate over a sequence of numbers like that, use xrange.)

Adbot
ADBOT LOVES YOU

Bozart
Oct 28, 2006

Give me the finger.

Habnabit posted:

As has been mentioned, tuples are immutable and hashable, which means they can be used as dictionary keys and in a myriad of other places where lists can't.


It was my understanding that they are only hashable if they include only hashable elements, although I could be completely wrong.

ashgromnies
Jun 19, 2004
After learning that you can use tuples as hash keys it took another tenth of a second off my program execution time on average! Woo!

So I feel REALLY embarrassed for asking this one, but how can you put variables inline? I'm writing some CSS out from a Python script(eventually I will do this the right way with templating, this is just for a really quick prototype though so it's not necessary at the moment) and I need to embed variables and it looks really ugly:

code:
f=open('colors.css', 'w')
f.write("""
	div {
		width: 50px;
		height: 50px;
	}
	div#container {
		width: 1024px;
		height: 1024px;
		background: url(
""")
f.write(infile)
f.write(""")
	}""")
for idx, hue in enumerate(hueList):
	if vibrant:
		rgb = hsl2rgb((hue, .625, lgtHistogram[(hue,'count')]/lgtHistogram[(hue,'total')]))
	else:
		rgb = hsl2rgb((hue, satHistogram[(hue,'count')]/satHistogram[(hue,'total')], lgtHistogram[(hue,'count')]/lgtHistogram[(hue,'total')]))
	f.write("#div")
	f.write(str(idx))
	f.write("""a {
		background-color: rgb(""")
	f.write(str(int(rgb[0])))
	f.write(",")
	f.write(str(int(rgb[1])))
	f.write(",")
	f.write(str(int(rgb[2])))
	f.write(""")
		}
""")

f.close()
I know I could do it way better but I don't know how :(

Suggestions?

Scaevolus
Apr 16, 2007

ashgromnies posted:

After learning that you can use tuples as hash keys it took another tenth of a second off my program execution time on average! Woo!

So I feel REALLY embarrassed for asking this one, but how can you put variables inline? I'm writing some CSS out from a Python script(eventually I will do this the right way with templating, this is just for a really quick prototype though so it's not necessary at the moment) and I need to embed variables and it looks really ugly:

I know I could do it way better but I don't know how :(

Suggestions?

You really do want Templating.

Or at least the basic String Formatting Operations.

code:
	f.write("#div")
	f.write(str(idx))
	f.write("""a {
		background-color: rgb(""")
	f.write(str(int(rgb[0])))
	f.write(",")
	f.write(str(int(rgb[1])))
	f.write(",")
	f.write(str(int(rgb[2])))
	f.write(""")
		}
"""
becomes
code:
f.write("""#div%da {
    background-color: rgb(%d,%d,%d)
}""" % (idx, rgb[0], rgb[1], rgb[2]))

Scaevolus fucked around with this message at 19:06 on May 30, 2008

ashgromnies
Jun 19, 2004

Scaevolus posted:

You really do want Templating.

Or at least the basic String Formatting Operations.

code:
	f.write("#div")
	f.write(str(idx))
	f.write("""a {
		background-color: rgb(""")
	f.write(str(int(rgb[0])))
	f.write(",")
	f.write(str(int(rgb[1])))
	f.write(",")
	f.write(str(int(rgb[2])))
	f.write(""")
		}
"""
becomes
code:
f.write("""#div%da {
    background-color: rgb(%d,%d,%d)
}""" % (idx, rgb[0], rgb[1], rgb[2]))

Yeah, I know I want templating but this is just a one-off for now to test my algorithm and will go away so I don't want to put too much effort into it - just enough to be readable. This is eventually going to be called from a Django application.

I didn't know Python had an equivalent of sprintf! Thanks!

hey mom its 420
May 12, 2007

Also, it might do you good to use the named string formatting for more readability.
code:
"Hello my name is %(name)s and I'm %(age)d years old" % {
   'name':'Bonus',
   'age':12,
}

king_kilr
May 25, 2007

ashgromnies posted:

Yeah, I know I want templating but this is just a one-off for now to test my algorithm and will go away so I don't want to put too much effort into it - just enough to be readable. This is eventually going to be called from a Django application.

I didn't know Python had an equivalent of sprintf! Thanks!

If this is for use in a Django app, you should probably take a look at the Django templating language.

ashgromnies
Jun 19, 2004

king_kilr posted:

If this is for use in a Django app, you should probably take a look at the Django templating language.

Yeah, I know the Django templating language. It's pretty easy.

Believe me, I know alllll about templating and what it gives you, this is just for a one-off for prototyping and I'd never really do this in an application :)

Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.

Bozart posted:

It was my understanding that they are only hashable if they include only hashable elements, although I could be completely wrong.

That's correct. Tuples hash the hashes of their contents.

Flea110
Apr 3, 2006
How do I get the indexes of every instance of a given character in a given string?

string.find seems to only give the index of the first instance.

Flea110 fucked around with this message at 21:03 on Jun 2, 2008

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Flea110 posted:

How do I get the indexes of every instance of a given character in a given string?

string.find seems to only give the index of the first instance.

code:
def findall(s, substr):
    all = []
    next = s.find(substr)
    while next != -1:
        all.append(next)
        next = s.find(substr, next + 1)
    return all

hey mom its 420
May 12, 2007

code:
def indices(c, st):
    return [i for k, i in zip(list(st), itertools.count()) if k==c]

deimos
Nov 30, 2006

Forget it man this bat is whack, it's got poobrain!
And if you want the count of every character in a string:
code:
from collections import defaultdict

def letter_counts(st):
    counts = defaultdict(int)
    for l in st:
        counts[l] += 1
    return counts
This returns a defaultdict (basically a dict with some extra hotness), the way you would use it is:
code:
blah = "donges and buttes"
counts = letter_counts(blah)

('a' in counts) 
#Returns false (also counts.get('a') should return None
#Important note: counts['a'] sets counts['a'] to 0

counts['e'] #Returns 2
edit:

Habnabit posted:

Fixed in bold.

Ahh crap I did the wrong import meant to from collections import defaultdict. And you're entirely right about __getitem__, my brain farted.

deimos fucked around with this message at 02:19 on Jun 3, 2008

Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.

deimos posted:

And if you want the count of every character in a string:
code:
import [b]collections[/b]

def letter_counts(st):
    counts = [b]collections.[/b]defaultdict(int)
    for l in st:
        counts[l] += 1
    return counts
This returns a defaultdict (basically a dict with some extra hotness), the way you would use it is:
code:
blah = "donges and buttes"
counts = letter_counts(blah)

[b]counts['a'] > 0[/b]
#Returns false ([b]no exception is raised when accessing a defaultdict, as the
defaultdict sets the value of a key if a key is missing. This is also why you 
can't just check [fixed]'a' in counts[/fixed] as [fixed]counts['a'][/fixed] could be 0.[/b])

counts['e'] #Returns 2

Fixed in bold.

tripwire
Nov 19, 2004

        ghost flow

Benji the Blade posted:

I am by NO means a PyPy expert, though I do think it's pretty cool.

The developers say PyPy is a tool for generating virtual machines. PyPy started as a Python interpreter written in Python, and it can still be used as such on top of CPython and you get an ungody slow Python interpreter. And so, they decided to write a translation layer that takes RPython (a subset of Python) and translates it into C code. They then wrote the interpreter in RPython and now the interpreter can be translated into C code, and is currently around twice as slow as CPython.

However, they can use a different translator to automatically translate PyPy onto different platforms such as CLI/.NET, JVM, and apparently also less obviously useful platforms such as Smalltalk and Scheme.

Of course, the translator will translate anything from RPython to C/CLI/JVM or whatever, so people can write whatever interpreters or other programs they like in RPython (though using RPython in production isn't really advised right now, from what I can tell). You can also use RPython to generate libraries for CPython that have been translated into C and compiled.

Anyway, they're working on things like JIT compilation/optimization and messing around with writing plugins for PyPy to change the behavior of the language in various ways (like reimplementing Stackless).

Really, the interesting thing to me is that if PyPy really takes off, it promises to make Jython and IronPython and CPython obsolete, since it could be run on pretty much any platform. I'd also like to see a stable RPython that would be useful for application developers to write high performance Python. Of course, if they get the JIT compiler in order, you should pretty much get the same speed boost out of any piece of your code that conforms to the constraints of RPython, even if it's embedded in the middle of your Python program. Sadly, I keep reading that the JIT is currently pretty seriously broken, so who knows if it'll ever pan out.

If you're interested in the gritty details of it all, this Google Tech Talk goes into some depth on it. The sound gets better after a little while, but it's still kinda a lacking presentation.
This is a really cool post; I have a somewhat dumb followup question that you or someone else might be able to answer for me.

One of the things the pypy people mentioned was improving the performance and portability of the interpreter to the point where it would be faster and more compatible than ironpython/cpython/jython; specifically they mentioned picking up where psyco left off in terms of speeding up cpu-bound code. I realize one of the stated goals of pypy over psyco is that its not as dependant on architecture, but will pypy fully support 64-bit processors/code, and how easily will it mesh with parallel python or pyprocessing? I never even bothered to download and compile python in 32-bit compatibility mode to take advantage of psyco, and if I did I suspect it wouldn't play nice with parallel python, although I haven't tried it yet.
In a nutshell, does anyone know if the devs of pypy going to make it work out of the box on multicore systems on a 64-bit os?

m0nk3yz
Mar 13, 2002

Behold the power of cheese!

tripwire posted:

This is a really cool post; I have a somewhat dumb followup question that you or someone else might be able to answer for me.

One of the things the pypy people mentioned was improving the performance and portability of the interpreter to the point where it would be faster and more compatible than ironpython/cpython/jython; specifically they mentioned picking up where psyco left off in terms of speeding up cpu-bound code. I realize one of the stated goals of pypy over psyco is that its not as dependant on architecture, but will pypy fully support 64-bit processors/code, and how easily will it mesh with parallel python or pyprocessing? I never even bothered to download and compile python in 32-bit compatibility mode to take advantage of psyco, and if I did I suspect it wouldn't play nice with parallel python, although I haven't tried it yet.
In a nutshell, does anyone know if the devs of pypy going to make it work out of the box on multicore systems on a 64-bit os?

I think the problem right now for PyPy is turning itself from little more than a science project into something more concrete. Right now they're still fiddling around with a lot of stuff (see: http://morepypy.blogspot.com/) and either they're lacking resources or focus. Of course, maybe I'm too focused on shipping stuff.

As for how well it would mesh with PP and PyProcessing: We'll see. It looks like my Pep (371) is getting accepted, and some of the ramifications of that may be some work on my part (or others) to port the module to jython/ironpython/pypy - but given the lack of GIL on the first two, it may not need to be ported.

Bozart
Oct 28, 2006

Give me the finger.

tripwire posted:

I'm modifying the source of neat-python, which is a pretty decent implementation of NEAT to use.
One of the benefits of python that I'm really enjoying is how understandable the code is; if you want to learn about how neuroevolution works I'd recommend studying neat-python code over any of the c++ or even java implementations, which had a lot more code devoted to just making things work, or work fast. A lot of people will bitch and moan that python isn't suitable for number crunching but really that is misleading I think.

All of the CPU intensive parts of this code can be sped up by using psyco and special optimized c++ libraries for manipulating neural nets, but because I'm using this 32-bit simulation environment and my native python is incompatible (64-bit), I have to use the python packaged with the simulator, version 2.3. Because this interpreter is incompatible with my installed modules, I've simply been throwing my modified neat-python folder into the simulation directory and waiting for the simulator developer to hurry up and throw python 2.5 in there.

Right now I've pretty much mangled the code in my attempts to implement a steady state algorithm novelty search (first time using python, it's been a real learning experience), but once I'm satisfied thats its cleaned up enough to be legible and understandable (and once it works properly) I'll ask the dev to throw it on the SVN. Which is here by the way: http://code.google.com/p/neat-python/source/browse

I know this was a ways back, but thanks for this -- I've been going through the papers on NEAT and reading some of the python code and it is exactly what I have been looking for.

chips
Dec 25, 2004
Mein Führer! I can walk!
I haven't done much Python before, so I was playing around with reimplementing some PHP experiment code I'd made. What the PHP code did was use reflection to take a method of a class, discover its arguments, and then allow a http GET to call that method, using the GET arguments as arguments for the function.

I worked out how to discover the number of arguments of a method/function in Python, but it doesn't seem to have a way to discover the names of the arguments - anyone know if there would be a way to do this? I realize that in many languages, this probably doesn't make sense, since the names of arguments are just labels local to the definition of the function. If anyone has a nice guide on reflection in Python, it'd be appreciated - I could only find some rather obtuse references that led me to find im_func and so on, which I have to admit is slightly easier than PHP5's reflection methods.

No Safe Word
Feb 26, 2005

chips posted:

I worked out how to discover the number of arguments of a method/function in Python, but it doesn't seem to have a way to discover the names of the arguments - anyone know if there would be a way to do this? I realize that in many languages, this probably doesn't make sense, since the names of arguments are just labels local to the definition of the function. If anyone has a nice guide on reflection in Python, it'd be appreciated - I could only find some rather obtuse references that led me to find im_func and so on, which I have to admit is slightly easier than PHP5's reflection methods.

You can do it, but it's not for the faint of heart.
code:
>>> def foo(a, b):
...     pass
...
>>> foo.func_code.co_varnames
('a', 'b')
Check out the Internal Types / Code Objects section here: http://www.python.org/doc/current/ref/types.html

I've never really messed with it, but I am marginally familiar with tooling around with func_code stuff because of this little tutorial/link on exploring Python bytecode: http://thermalnoise.wordpress.com/2007/12/30/exploring-python-bytecode/

edit: haha, and right after I made the post I noticed this:
code:
>>> help(foo.func_code)
class code(object)
 |  code(argcount, nlocals, stacksize, flags, codestring, constants, names,
 |        varnames, filename, name, firstlineno, lnotab[, freevars[, cellvars]])
 |
 |  Create a code object.  [b][u]Not for the faint of heart.[/u][/b]
edit2: and also some friends pointed out that the inspect module can do this too with the getargspec function. See the inspect page: http://docs.python.org/lib/module-inspect.html

No Safe Word fucked around with this message at 16:28 on Jun 3, 2008

chips
Dec 25, 2004
Mein Führer! I can walk!
That's great, thanks a lot.

SmirkingJack
Nov 27, 2002
Oh, so this is what Python is all about.

Bozart
Oct 28, 2006

Give me the finger.

Bozart posted:

I know this was a ways back, but thanks for this -- I've been going through the papers on NEAT and reading some of the python code and it is exactly what I have been looking for.

OK so I'm a total newbie and an idiot and basically I do everything wrong all the time. I downloaded the neat-python code from the google code cvs, but I can't get any of the examples to run. I'm running python 2.5.2. When I do

import neat

in IDLE, from the directory above where I have the neat folder, it runs without a problem, but it doesn't do anything - the __init__.py file is empty. And when I try to run the setup.py function that comes with it, it just errors out. And when I try to run the examples it can't import anything from neat. Normally I would (and tried) to sit down and go through what could be going wrong, but for a new language with a new package, with no documentation, I am at a loss. I don't know if I maybe got the wrong files from google, or what?

hey mom its 420
May 12, 2007

From the commandline, try navigating to the
code:
neat
directory and type in
code:
python setup.py install
at the terminal. I'm not sure if that's the procedure for that particular package, but that's how it usually goes.

ashgromnies
Jun 19, 2004
So I'm writing a method in a class that I want to be able to be accessed without instantiating the class, or if it's called from an instance of the class to use the variables inside the class.

Here's what I'm trying to do(and it's not working):

code:
class Pixel:
	def __init__(self, colorhash):
		if colorhash.get('r') and colorhash.get('g') and colorhash.get('b'):
			# rgb
			self.red = colorhash['r']
			self.green = colorhash['g']
			self.blue = colorhash['b']
		elif colorhash.get('h') and colorhash.get('s') and colorhash.get('l'):
			# hsl
			raise LazyCoderError, "this isn't done yet"
		else:
			raise ValueError, "Did not pass in proper {'r': #, 'g': #, 'b': #} or {'h': #, 's': #, 'l': #} hash to __init__"

	def getLight(self, pixel=(self.red, self.green, self.blue)):
		maxi, dom = max((v, i) for i, v in enumerate(pixel))
		mini, dim = min((v, i) for i, v in enumerate(pixel))
		light = 0.5 * (maxi + mini)
		return light
Behavior I want(hey, this sounds like a GREAT excuse to learn the Python unit testing framework):

code:
>>> Pixel.getLight((0,255,255))
255
>>> p = Pixel({'r': 0, 'g': 255, 'b': 255})
>>> p.getLight()
255
Can anyone help me figure out what I need to do to get to that point? I'm still a Python noob coming over from Perl :)

Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.

ashgromnies posted:

:words:

I'm not sure whether this is it, but there's at least one thing to try:
code:
def getLight(self):
	pixel = self.red, self.green, self.blue
	maxi, dom = max((v, i) for i, v in enumerate(pixel))
	mini, dim = min((v, i) for i, v in enumerate(pixel))
	light = 0.5 * (maxi + mini)
	return light
Default arguments are evaluated at compile time, not call time. Also, you should use 'r' in colorhash etc., because colorhash.get('r') would evaluate to False if colorhash['r'] is 0.

Habnabit fucked around with this message at 04:21 on Jun 4, 2008

Bozart
Oct 28, 2006

Give me the finger.

Bonus posted:

From the commandline, try navigating to the
code:
neat
directory and type in
code:
python setup.py install
at the terminal. I'm not sure if that's the procedure for that particular package, but that's how it usually goes.

Thanks for the pointer. I am now somewhat closer to my goal, however I wasn't kidding when I said I basically screw everything up.

It gives an error about having been built in VS2003 (the extensions for neat-python are written in c++) and that extensions have to be built using the same compiler. I don't own VS2003, but it also said that you can build it with mingw32. OK, sweet, I downloaded and installed mingw32, and then tried again with the additional option

code:
setup.py install -c mingw32
just like it suggests, but then it bombs out with the error message that mingw32 is an unrecognized command.

So I installed cygwin and then installed python under it, and installed gcc as well. Things compiled fine but now I can't use eclipse. (this is making me think I am doing things very wrong)

Also, when I tried to run the example/single_pole.py it tries to import genome2.py, I think, and that file or directory just doesn't exist. Help me please!

Scaevolus
Apr 16, 2007

ashgromnies posted:

code:
		if colorhash.get('r') and colorhash.get('g') and colorhash.get('b'):

In Python, 0 evaluates to False. (What you want is colorhash.has_key('r'))

tripwire
Nov 19, 2004

        ghost flow

Bozart posted:

Thanks for the pointer. I am now somewhat closer to my goal, however I wasn't kidding when I said I basically screw everything up.

It gives an error about having been built in VS2003 (the extensions for neat-python are written in c++) and that extensions have to be built using the same compiler. I don't own VS2003, but it also said that you can build it with mingw32. OK, sweet, I downloaded and installed mingw32, and then tried again with the additional option

code:
setup.py install -c mingw32
just like it suggests, but then it bombs out with the error message that mingw32 is an unrecognized command.

So I installed cygwin and then installed python under it, and installed gcc as well. Things compiled fine but now I can't use eclipse. (this is making me think I am doing things very wrong)

Also, when I tried to run the example/single_pole.py it tries to import genome2.py, I think, and that file or directory just doesn't exist. Help me please!
Yeah I think I went through the same pain as you did at first. The examples might take a bit of massaging to get to work correctly, however you do NOT require the c++ extensions through psyco; there is python activation functions you can use instead, theyre just not as fast (this is what I do because they don't make psyco for 64 bit architectures).

You can run the setup.py file which will throw all the modules into your python base installation; this can sometimes mess with eclipse if the pythonhome and pythonpath environment variables get changed (try resetting or unsetting them if eclipse complains).

The way I usually run fitness tests is with Breve, (a simulator with its own prepackaged python interpreter). Since breve won't let me load my own python modules due to wanting 32-bit python and me having 64-bit python, to get around that I throw my source code (the entire "neat" directory) into the directory where my simulation file is.

That way a call to "import neat" in my simulation file will cause python to check locally before looking for neat in your python home directory. You can do this as well if you like.
If you are patient I'll show you my changes to the code and go over any questions you have about getting it to work; usually the only problem is the pythonpath and pythonhome variables. I'm just going to clean it up a bit and I'll upload it later.

ashgromnies
Jun 19, 2004

Habnabit posted:

I'm not sure whether this is it, but there's at least one thing to try:
code:
def getLight(self):
	pixel = self.red, self.green, self.blue
	maxi, dom = max((v, i) for i, v in enumerate(pixel))
	mini, dim = min((v, i) for i, v in enumerate(pixel))
	light = 0.5 * (maxi + mini)
	return light
Default arguments are evaluated at compile time, not call time. Also, you should use 'r' in colorhash etc., because colorhash.get('r') would evaluate to False if colorhash['r'] is 0.

But that doesn't let me call that without instantiating an instance of the class.

Something similar to this is what I need, I think, I'm just having trouble figuring out where to take it:

code:
>>> class Pixel:
...     def __init__(self,rgb):
...             self.red = rgb[0]
...             self.green = rgb[1]
...             self.blue = rgb[2]
...     def getSum(self, pixel=()):
...             if not len(pixel):
...                     pixel = (self.red, self.green, self.blue)
...             return pixel[0] + pixel[1] + pixel[2]
... 
>>> Pixel.getSum((1,2,3))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method getSum() must be called with Pixel instance as first argument (got tuple instance instead)
>>> p = Pixel((1,2,3))
>>> p.getSum()
6
>>> p.getSum((5,6,7))
18
How do I get it so I can call it on the class itself without an instance of the object? I know it has to do with it expecting self in its arguments.

Thanks for telling me about has_key, I didn't know that! I would have been scratching my head if a bug due to that came up.

Chewing through the docs, I found another very important fact that I will need to watch out for because I'm treading on dangerous water in regards to it now:

http://docs.python.org/ref/function.html posted:

Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that that same ``pre-computed'' value is used for each call. This is especially important to understand when a default parameter is a mutable object, such as a list or a dictionary: if the function modifies the object (e.g. by appending an item to a list), the default value is in effect modified. This is generally not what was intended. A way around this is to use None as the default, and explicitly test for it in the body of the function

I really need to check out Python unit testing. It looks like you can just write the expected output from calling it in the interactive interpreter, which is really cool. Anyone have experience?

ashgromnies fucked around with this message at 06:04 on Jun 4, 2008

Allie
Jan 17, 2004

A tuple is immutable, it isn't an issue there. And you want @classmethod:
code:
>>> class Foo(object):
...     @classmethod
...     def bar(cls, baz):
...         print baz
... 
>>> Foo.bar(5)
5
Also I'm not sure what you're referring to with unit testing there. Python has several testing libraries, like doctest, which tests code examples of interactive interpreter output in doc strings, and unittest, which is a huge Java-like piece of poo poo.

nose is nice too. With nose you can just write functions starting with test_ and use assert.

ashgromnies
Jun 19, 2004

Milde posted:

A tuple is immutable, it isn't an issue there. And you want @classmethod:
code:
>>> class Foo(object):
...     @classmethod
...     def bar(cls, baz):
...         print baz
... 
>>> Foo.bar(5)
5
Also I'm not sure what you're referring to with unit testing there. Python has several testing libraries, like doctest, which tests code examples of interactive interpreter output in doc strings, and unittest, which is a huge Java-like piece of poo poo.

nose is nice too. With nose you can just write functions starting with test_ and use assert.

I keep forgetting tuples are immutable, oops. Thanks.

The class method lets me run it on the class, yeah, but then I can't run it based on the values inside of an instance. I'd have to make two methods(one for class, one for instance) with different names and I don't want to do that because I'm a lazy programmer with a poor memory and two methods is too many to remember(or I just want to do this to figure out how).

I had a crackpot scheme, this is probably the wrong way to do it.

What if I defined a "getLight" class method on Pixel that expected a tuple and did the work required on it and returned the results.

Then in the __init__ method I could dynamically override the getLight method to be an instance method that would calculate it based on the values in self.

Is that correct or is there a better way?

ashgromnies fucked around with this message at 06:22 on Jun 4, 2008

Allie
Jan 17, 2004

What are you trying to accomplish? Why can't you have an instance method that returns a new instance? You can't have a class method that accesses an instance if it doesn't have an instance to access. I think you're trying to make whatever you're doing more complicated than it needs to be.

Maybe you mean something like this?

code:
>>> class Foo(object):
...     pass
... 
>>> def create_or_modify_foo(someval, foo=None):
...     if foo is None:
...         foo = Foo()
...     foo.bar = someval
...     return foo
... 
>>> create_or_modify_foo(5).bar
5
>>> create_or_modify_foo(5, Foo()).bar
5
Also, if seq and if len(seq) are the same thing. You should generally always use the former.

No Safe Word
Feb 26, 2005

Scaevolus posted:

In Python, 0 evaluates to False. (What you want is colorhash.has_key('r'))

Is there really ever a reason to use has_key now that you can just use in? (Honest question, not snarky contrary response)

code:
if 'r' in colorhash and 'g' in colorhash and 'b' in colorhash:
    stuff
versus

code:
if colorhash.has_key('r') and colorhash.has_key('g') and colorhash.has_key('b'):
    stuff

Allie
Jan 17, 2004

has_key is apparently technically slower than in, but I personally don't use it for style reasons. It's easier to read the operator than the method call, at least in my opinion, and it matches up with membership tests for sequences.

It's also slated for removal in Python 3.0.

ashgromnies
Jun 19, 2004
I'm unsure of where you were going with your last example, but I got an example of the behavior I wanted working:

code:
>>> def test(testobject):
...     print "instance method"
... 
>>> class TestClass:
...     @classmethod
...     def test(cls, *args):
...             print "class method"
...     def __init__(self):
...             import new
...             test_method = new.instancemethod(test, self, self.__class__)
...             self.__dict__['test'] = test_method
... 
>>> TestClass.test()
class method
>>> t = TestClass()
>>> t.test()
instance method
>>> TestClass.test()
class method

Allie
Jan 17, 2004

I still have no idea what you're trying to accomplish, but it looks like you're making things more complicated than they need to be.

And while we're talking about style, you should be using new-style classes (e.g. class TestClass(object):) and you should just assign the attribute directly, instead of using __dict__.

Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.

ashgromnies posted:

I'm unsure of where you were going with your last example, but I got an example of the behavior I wanted working:

That's a little messy. Why don't you just do it like this?

code:
class Pixel:
	def __init__(self, colorhash):
		if 'r' in colorhash and 'g' in colorhash and 'b' in colorhash:
			# rgb
			self.red = colorhash['r']
			self.green = colorhash['g']
			self.blue = colorhash['b']
		elif 'h' in colorhash and 's' in colorhash and 'b' in colorhash:
			# hsl
			raise NotImplementedError
		else:
			raise ValueError
	def getLight(self):
	    return getLight((self.red, self.green, self.blue))

def getLight(pixel):
	maxi, dom = max((v, i) for i, v in enumerate(pixel))
	mini, dim = min((v, i) for i, v in enumerate(pixel))
	light = 0.5 * (maxi + mini)
	return light
Also, has_key is deprecated, as is the new module. Instead, use in and the types module, respectively. The future of types is unknown in py3k currently, though I think it might remain under a different name. new will be gone for sure, though.

ashgromnies
Jun 19, 2004

Habnabit posted:

That's a little messy. Why don't you just do it like this?

code:
class Pixel:
	def __init__(self, colorhash):
		if 'r' in colorhash and 'g' in colorhash and 'b' in colorhash:
			# rgb
			self.red = colorhash['r']
			self.green = colorhash['g']
			self.blue = colorhash['b']
		elif 'h' in colorhash and 's' in colorhash and 'b' in colorhash:
			# hsl
			raise NotImplementedError
		else:
			raise ValueError
	def getLight(self):
	    return getLight((self.red, self.green, self.blue))

def getLight(pixel):
	maxi, dom = max((v, i) for i, v in enumerate(pixel))
	mini, dim = min((v, i) for i, v in enumerate(pixel))
	light = 0.5 * (maxi + mini)
	return light
Also, has_key is deprecated, as is the new module. Instead, use in and the types module, respectively. The future of types is unknown in py3k currently, though I think it might remain under a different name. new will be gone for sure, though.

I don't really like that because I can't call getLight on the Pixel class so it makes it harder to encapsulate. I would need to import that method from the file Pixel is stored in as well. I'd rather have it all in one class if I could.

I will check out types and try to replace new with it.

Milde posted:

I still have no idea what you're trying to accomplish, but it looks like you're making things more complicated than they need to be.

And while we're talking about style, you should be using new-style classes (e.g. class TestClass(object):) and you should just assign the attribute directly, instead of using __dict__.

Ahh, thanks.

I don't see how I'm making things more complicated - it makes them easier and more reusable in the end, in my opinion. The Pixel class contains methods that act on Pixels. Sometimes I don't actually have an instance of a Pixel and don't need to make one because I won't be using it any more but would like to perform certain operations on an arbitrary (r,g,b) tuplet.

ashgromnies fucked around with this message at 06:43 on Jun 4, 2008

Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.

ashgromnies posted:

I don't really like that because I can't call getLight on the Pixel class so it makes it harder to encapsulate. I would need to import that method from the file Pixel is stored in as well. I'd rather have it all in one class if I could.

I will check out types and try to replace new with it.

No you wouldn't. Everything in a module, including functions and classes, is created aware of its surroundings. If it was in a separate module, it wouldn't check the caller's global namespace; that wouldn't make sense. It would check the global namespace in which it was defined.

Besides, it's rather weird to do it the way you want. Why not then just make one function and call that?
code:
def getLight(pixel):
    pixel = list(pixel)
    maxi, dom = max((v, i) for i, v in enumerate(pixel))
    mini, dim = min((v, i) for i, v in enumerate(pixel))
    light = 0.5 * (maxi + mini)
    return light
This, and then make Pixels convertible to lists.

e: stupid textmate, mixing tabs and spaces. :argh:

ashgromnies posted:

I don't see how I'm making things more complicated - it makes them easier and more reusable in the end, in my opinion. The Pixel class contains methods that act on Pixels. Sometimes I don't actually have an instance of a Pixel and don't need to make one because I won't be using it any more but would like to perform certain operations on an arbitrary (r,g,b) tuplet.
What might seem easier or more intuitive can sometimes make more fragile code. I've seen some pretty broken APIs that rely on isinstance or type calls to try to determine what to do with the arguments passed to a method, effectively limiting themselves in the name of "convenience."

Habnabit fucked around with this message at 06:48 on Jun 4, 2008

Adbot
ADBOT LOVES YOU

ashgromnies
Jun 19, 2004

Habnabit posted:

No you wouldn't. Everything in a module, including functions and classes, is created aware of its surroundings. If it was in a separate module, it wouldn't check the caller's global namespace; that wouldn't make sense. It would check the global namespace in which it was defined.

Besides, it's rather weird to do it the way you want. Why not then just make one function and call that?
code:
def getLight(pixel):
    pixel = list(pixel)
    maxi, dom = max((v, i) for i, v in enumerate(pixel))
    mini, dim = min((v, i) for i, v in enumerate(pixel))
    light = 0.5 * (maxi + mini)
    return light
This, and then make Pixels convertible to lists.

e: stupid textmate, mixing tabs and spaces. :argh:

I don't want to do that because getting lightness is a function associated with pixels so I want it to be in their class.

This is what I meant by "I would need to import that method":

code:
~/bin> cat pixel.py
class Pixel:
    def __init__(self, colorhash):
        if 'r' in colorhash and 'g' in colorhash and 'b' in colorhash:
            # rgb
            self.red = colorhash['r']
            self.green = colorhash['g']
            self.blue = colorhash['b']
        elif 'h' in colorhash and 's' in colorhash and 'b' in colorhash:
            # hsl
            raise NotImplementedError
        else:
            raise ValueError
    def getLight(self):
        return getLight((self.red, self.green, self.blue))

def getLight(pixel):
    maxi, dom = max((v, i) for i, v in enumerate(pixel))
    mini, dim = min((v, i) for i, v in enumerate(pixel))
    light = 0.5 * (maxi + mini)
    return light
 


~/bin> python
>>> from pixel import Pixel
>>> getLight((1,2,3))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'getLight' is not defined
>>> Pixel.getLight((1,2,3))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method getLight() must be called with Pixel instance as first argument (got tuple instance instead)
>>> p = Pixel({'r':1, 'g':2, 'b':3})
>>> p.getLight()
2.0
>>> from pixel import Pixel, getLight
>>> getLight((1,2,3))
2.0

Habnabit posted:

What might seem easier or more intuitive can sometimes make more fragile code. I've seen some pretty broken APIs that rely on isinstance or type calls to try to determine what to do with the arguments passed to a method, effectively limiting themselves in the name of "convenience."

Maybe I'm not going about this in the Python way. I'm not really sure how people normally solve this problem in Python but I like being able to call methods on the class since it performs logic that only makes sense in the context of that class.

ashgromnies fucked around with this message at 06:54 on Jun 4, 2008

  • Locked thread