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
Bozart
Oct 28, 2006

Give me the finger.

ashgromnies posted:

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
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.

it seems to me your rgb and hsl switch is more like a couple of subclasses waiting to happen. Aren't they just two different types of pixles, each of which should have their own implementation of the getlight method?

Adbot
ADBOT LOVES YOU

Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.
Okay, I've just spent a few minutes hacking at this to try to get some sort of consistent, clean interface. I think it's just a ridiculous request. You could add a classmethod to the class for operating on tuples, then call Pixel.staticGetLight or whatever and then have getLight call that with itself.

It would be easier to either (1) only use a function, instead of a method or (2) have a classmethod and an instance method like how I described above.

ashgromnies
Jun 19, 2004

Bozart posted:

it seems to me your rgb and hsl switch is more like a couple of subclasses waiting to happen. Aren't they just two different types of pixles, each of which should have their own implementation of the getlight method?

getLight exists to grab a lightness value from an rgb pixel. You may be right unless you're just playing with me, I'm really tired right now.

I need to look up how casting works in Python so I can make rgb convertible to hsl and vice versa just by going

code:
>>> rgb = RGBPixel(255,255,255)
>>> hsl = HSLPixel(rgb)
>>> hsl
Hue: 0
Saturation: 100
Lightness: 100
>>> hsl = HSLPixel(0,100,100)
etc.

This is starting to look overengineered. Why the hell am I doing this. I need to get some sleep. Thanks, guys.

bbq
Jan 21, 2006

get funky.
If you really want to have all the functions be a member of the Pixel class, this works:
code:
class Pixel(object):
	def __init__(self, rgb):
		(self.red, self.green, self.blue) = rgb
		def getSum():
			return Pixel.getSum((self.red, self.green, self.blue))
		self.getSum = getSum
	
	@staticmethod
	def getSum(pixel):
		return pixel[0] + pixel[1] + pixel[2]
But I agree with the others, this is the wrong way to go about it.

ashgromnies
Jun 19, 2004

bbq posted:

If you really want to have all the functions be a member of the Pixel class, this works:
code:
class Pixel(object):
	def __init__(self, rgb):
		(self.red, self.green, self.blue) = rgb
		def getSum():
			return Pixel.getSum((self.red, self.green, self.blue))
		self.getSum = getSum
	
	@staticmethod
	def getSum(pixel):
		return pixel[0] + pixel[1] + pixel[2]
But I agree with the others, this is the wrong way to go about it.

Can you please tell me why this is the wrong way to go about it? What would you recommend instead? It doesn't make sense to me to have to call Pixel.staticGetLight if I don't have an instance and p.getLight if I do have an instance.

I could use a function instead of a method but then I have to import it separately from the class or from pixel import * which pollutes my namespace in my opinion.

edit:

I think I just realized why it's a bad idea - this is going to require me to maintain it in multiple places. I can use an approach like bbq gave to avoid repeating myself. I guess I'm kind of thinking of the class as a namespace in which to store functions, as well as being instantiable. I guess it's acceptable to pollute my global namespace in Python by importing the method when I need it.

ashgromnies fucked around with this message at 15:23 on Jun 4, 2008

hey mom its 420
May 12, 2007

I found that Java-ish static methods are best translated to module top level functions in Python.

Dr-NiKoN
Jan 17, 2004
foo
Python Cookbook.

code:
class Callable:
  def __init__(self, anycallable):
    self.__call__ = anycallable

class foo(object):	  
  def talk():
    print "Hello World"
    
  talk = Callable(talk)
    
    
if __name__ == "__main__":
  
  # "Static" class method
  foo.talk()
  
  bar = foo()

  # "Instance" method
  bar.talk()

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
How do you refer to "self" inside talk(), though?

Dr-NiKoN
Jan 17, 2004
foo
You would have to pass it in, which kinda breaks the OO-paradigm.

You could do:
code:
class foo():
  def __init__(self, data):
    self.data = data

  def talk(input):
    print input

  talk = Callable(talk)
But, you would end up with poo poo like this:
code:
bar = class("Hello World")
bar.talk(bar.data) :psyduck:
Back to the drawing board I guess.

Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.
I tried something like this:
code:
class Callable:
    def __init__(self, anycallable):
        self.callable = anycallable
    def __call__(self, *a, **kw):
        return self.callable(*a, **kw)
    def make_function(self):
        def func(*a, **kw):
            return self(*a, **kw)
        return func

class foo(object):	    
    def talk(self=None):
        print self
        
    talk = Callable(talk).make_function()
as python won't bind callable objects to methods, but it will bind functions. This doesn't work, though, as it's basically an obtuse wrapper around the function that doesn't actually do anything. Callable is just an obtuse wrapper around staticmethod, too.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

ashgromnies posted:

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

There's nothing wrong with this method - in fact it's a pretty cool hack. The problem is that all the ugliness is up front where you can see it. If you push it down into another module, you could just do this:

code:
import classmethod_override

@classmethod_override.override({"test": _test})
class TestClass:
    def _test(self):
        print "instance method"
    @classmethod
    def test(cls):
        print "class method"
Which says, "When instantiating this class, override the classmethod test with the instance method _test. (And since it's a map, you can override a bunch of methods in the same call.)

At least, you could do that if class decorators were allowed, which they're not. (Boo!) So instead you'll have to apply the decorator to __init__ - which actually makes more sense, from a certain point of view, since it makes it explicit that you're messing with the instance that's being initialized, not the class as it's being defined.

code:
import classmethod_override

class TestClass:
    def _test(self):
        print "instance method"
    @classmethod
    def test(cls):
        print "class method"
    @classmethod_override.override({"test": _test})
    def __init__(self):
        pass
So what does classmethod_override look like?

code:
# define a decorator that takes a map argument instead of a function
def override(map):

    # it returns a nested decorator that takes a function argument
    def decorator(func):
        if func.__name__ != "__init__":
            return func    # only allow this decorator to apply to __init__

        # the nested decorator returns a wrapped init method that applies the map
        # of method overrides and then calls the real init method
        def __init__(self, *args, **kwargs):
            for name in map:
                self.__dict__[name] = new.instancemethod(map[name], self, self.__class__)
            return func(self, *args, **kwargs)

        return __init__

    return decorator
It's ugly to define, but using it isn't ugly at all.

Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.

JoeNotCharles posted:

There's nothing wrong with this method - in fact it's a pretty cool hack. The problem is that all the ugliness is up front where you can see it. If you push it down into another module, you could just do this:

code:
import classmethod_override

@classmethod_override.override({"test": _test})
class TestClass:
    def _test(self):
        print "instance method"
    @classmethod
    def test(cls):
        print "class method"
Which says, "When instantiating this class, override the classmethod test with the instance method _test. (And since it's a map, you can override a bunch of methods in the same call.)

At least, you could do that if class decorators were allowed, which they're not. (Boo!) So instead you'll have to apply the decorator to __init__ - which actually makes more sense, from a certain point of view, since it makes it explicit that you're messing with the instance that's being initialized, not the class as it's being defined.

code:
import classmethod_override

class TestClass:
    def _test(self):
        print "instance method"
    @classmethod
    def test(cls):
        print "class method"
    @classmethod_override.override({"test": _test})
    def __init__(self):
        pass
So what does classmethod_override look like?

code:
# define a decorator that takes a map argument instead of a function
def override(map):

    # it returns a nested decorator that takes a function argument
    def decorator(func):
        if func.__name__ != "__init__":
            return func    # only allow this decorator to apply to __init__

        # the nested decorator returns a wrapped init method that applies the map
        # of method overrides and then calls the real init method
        def __init__(self, *args, **kwargs):
            for name in map:
                self.__dict__[name] = new.instancemethod(map[name], self, self.__class__)
            return func(self, *args, **kwargs)

        return __init__

    return decorator
It's ugly to define, but using it isn't ugly at all.

No, you're completely wrong. This is not a cool hack by any means. This is ridiculous, and you've only made it more ridiculous. (Why does it fail silently if the method isn't __init__?) The simplest way to do this is to use a global function. Every other way is either absolutely ridiculous and requires code duplication[1], like this, or requires two separate methods in the class, which is apparently unacceptable.

[1] see: http://codepad.org/8LbuQJAc

Scaevolus
Apr 16, 2007

Milde posted:

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__.

I read this once before, but I can't find it again. What's the difference between old and new-style classes?

Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.

Scaevolus posted:

I read this once before, but I can't find it again. What's the difference between old and new-style classes?

New-style classes just implement some things that old-style classes don't have by default, like descriptors.
http://docs.python.org/ref/node33.html

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Habnabit posted:

No, you're completely wrong. This is not a cool hack by any means. This is ridiculous, and you've only made it more ridiculous. (Why does it fail silently if the method isn't __init__?) The simplest way to do this is to use a global function. Every other way is either absolutely ridiculous and requires code duplication[1], like this, or requires two separate methods in the class, which is apparently unacceptable.

[1] see: http://codepad.org/8LbuQJAc

You could assert or make it throw if the method isn't __init__, instead. In fact that's probably better. The point is that this decorator specifically hooks into instantiation, and it doesn't make sense to put it anywhere else.

What does the link you pasted have to do with code duplication? What, in fact, is the problem with that link? _test (which gets renamed to "test") is calling itself, which leads to infinite recursion, as expected. If you wanted it to call the classmethod version, use Foo.test.

The simplest way to do this is to use a global function, yes. But I'm not going for simplest - I'm going for most elegant API.

Allie
Jan 17, 2004

In Python simplicity is elegance. Nothing is more inelegant than code you have to spend extra time reading and comprehending in order to figure out what it's doing. Jumping back and forth and back and forth through different classes and different modules in order to get a general idea of how a library works is incredibly annoying, and I've had to do that with some Python libraries before.

It's even more depressing when you realize there was no reason for the code to do what it does the way it does, and that the entire thing could've been greatly simplified.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Milde posted:

In Python simplicity is elegance. Nothing is more inelegant than code you have to spend extra time reading and comprehending in order to figure out what it's doing. Jumping back and forth and back and forth through different classes and different modules in order to get a general idea of how a library works is incredibly annoying, and I've had to do that with some Python libraries before.

It's even more depressing when you realize there was no reason for the code to do what it does the way it does, and that the entire thing could've been greatly simplified.

API simplicity != implementation simplicity

If you're a user of TestClass, you don't need to care about how the classmethod_override library works, or even that it exists - all you need to know is that you can call the "test" method either as a class or an instance method.

If you're an implementor of TestClass, you need to know a little more - you need to know that you can't create two "test" methods directly, because the second one will just replace the first; you need to give the instance version a different name and then rename it using classmethod_override. You don't need to care about how classmethod_override actually works.

If you do want to know how classmethod_override actually works, it's not like it's hard to track down where that code is.

Allie
Jan 17, 2004

JoeNotCharles posted:

API simplicity != implementation simplicity

There are a lot of cases in Python where it isn't this simple. When I wrote that post I was specifically thinking of FormEncode, which does such absolutely mind-bogglingly ridiculous things with metaclasses that you can't even do simple things like instantiate a field without it being inside a form class. And in this case, this doesn't simplify the API at all. I've never ever seen anyone use a pattern like this in Python. I'd probably be scratching my head if I saw it, and honestly I'm still not sure what doing any of this would accomplish.

If you find yourself saying, "that's a cool hack," you should probably step back and think for a moment before you decide to soup up that hack even more.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Milde posted:

There are a lot of cases in Python where it isn't this simple. When I wrote that post I was specifically thinking of FormEncode, which does such absolutely mind-bogglingly ridiculous things with metaclasses that you can't even do simple things like instantiate a field without it being inside a form class.

Yes, obviously if you go too far you raise too many barriers to actually coding. I just don't think this particular example is all that complicated.

quote:

And in this case, this doesn't simplify the API at all. I've never ever seen anyone use a pattern like this in Python. I'd probably be scratching my head if I saw it, and honestly I'm still not sure what doing any of this would accomplish.

I think it'd be justified if I was cloning or wrapping a Java interface or something that does this and wanted to follow it as closely as possible, for example.

m0nk3yz
Mar 13, 2002

Behold the power of cheese!
PEP 371 has been accepted/final!

hey mom its 420
May 12, 2007

AWESOME!!!!!

Wulfeh
Dec 1, 2005

The mmo worth playing: DAoC
I am having some trouble receiving UDP packets via python script, but I can see that I am getting them through a network monitor called Wireshark. Basically my script looks like this:

code:
import socket

UDP_IP=''
UDP_PORT=27015

sock = socket.socket( socket.AF_INET,
                      socket.SOCK_DGRAM )
sock.bind((UDP_IP,UDP_PORT))
while True:
	data = sock.recvfrom(4096)
	print data
and the udp packet has this information:

69.12.53.114 192.168.1.125 UDP Source port: 27015 Destination port: 0

I understand you are supposed to use the destination port, but why is the destination port here specified as 0? How can I capture this data packet?

The packets are being sent from a TF2 Steam server, they are log messages.

Dr-NiKoN
Jan 17, 2004
foo

docs posted:

recvfrom( bufsize[, flags])
Receive data from the socket. The return value is a pair (string, address) where string is a string representing the data received and address is the address of the socket sending the data. The optional flags argument has the same meaning as for recv() above. (The format of address depends on the address family -- see above.)

try
code:
(data, header) = sock.recvfrom(4096)

Wulfeh
Dec 1, 2005

The mmo worth playing: DAoC

Dr-NiKoN posted:

try
code:
(data, header) = sock.recvfrom(4096)

Thanks for the catch, changed that, regardless of that though, I am not receiving a packet to begin with.

Allie
Jan 17, 2004

Wulfeh posted:

The packets are being sent from a TF2 Steam server, they are log messages.

Are you talking about the remote logging client in the HL2 server? That isn't enabled by default, and port 27015 is for game traffic, not logging. You have to add your logging server (the recipient) with logaddress_add.

If that's what you're actually trying to do, you might find this useful: http://bitheap.org/hg/hl2utils/. It has a very basic remote logging listener.

Wulfeh
Dec 1, 2005

The mmo worth playing: DAoC

Milde posted:

Are you talking about the remote logging client in the HL2 server? That isn't enabled by default, and port 27015 is for game traffic, not logging. You have to add your logging server (the recipient) with logaddress_add.

If that's what you're actually trying to do, you might find this useful: http://bitheap.org/hg/hl2utils/. It has a very basic remote logging listener.

Yea the server has my ip:port setup, and is sending my machine UDP packets, I can see them with Wireshark, and I can decode them and look at the log messages, the problem I am having is with Python picking up these packets as they are incoming

edit: I looked at that logging listener, and it's neat, i'll probably use it when I can figure out how to properly grab the packets

Wulfeh fucked around with this message at 01:46 on Jun 8, 2008

Allie
Jan 17, 2004

Wulfeh posted:

Yea the server has my ip:port setup, and is sending my machine UDP packets, I can see them with Wireshark, and I can decode them and look at the log messages, the problem I am having is with Python picking up these packets as they are incoming

edit: I looked at that logging listener, and it's neat, i'll probably use it when I can figure out how to properly grab the packets

According to the docs, an empty host string is equivalent to localhost. You probably meant to listen on 0.0.0.0.

Wulfeh
Dec 1, 2005

The mmo worth playing: DAoC
I set it to listen to 0.0.0.0 but I am unsure how to handle the UDP packet with a destination port of 0, is it maybe because of my router?

the TF2 server has logaddress_add with myip:27800 specified

Router is redirecting all data on port 27800 -> mylocalmachine

Could that affect the destination port?

deimos
Nov 30, 2006

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

Wulfeh posted:

I set it to listen to 0.0.0.0 but I am unsure how to handle the UDP packet with a destination port of 0, is it maybe because of my router?

the TF2 server has logaddress_add with myip:27800 specified

Router is redirecting all data on port 27800 -> mylocalmachine

Could that affect the destination port?

O hey I answered your question in #python.

Make the script listen on 27800.

Wulfeh
Dec 1, 2005

The mmo worth playing: DAoC

deimos posted:

O hey I answered your question in #python.

Make the script listen on 27800.

I got it, I am not sure exactly what is going on but the server admin changed the logaddress_add from url:port to my ip:port and it is now properly forwarding packets to 27800. The reason I was receiving packets from port 0 was because I set myself up as the DMZ earlier on and I was able to see all traffic.

zero knowledge
Apr 27, 2008
I'm working a summer internship research dealie at my university and I'm writing a small-to-medium program in Python to study Rubik's cubes and related puzzles (my professor discovered quantum teleportation and I end up working on Rubik's cubes... go figure).

I love Python, as it's certainly a huge step up from the JavaScript implementation my prof initially wanted me to do. I'm really enjoying learning a new language, especially one so different from the C/Java stuff my various homework assignments tend to be in, but there's one thing I'm having trouble with: standard library documentation.

I'm pretty used to languages like Java, C# on .NET or just plain old standard library C which are rigorously documented. Whatever else you want to say about Java and Sun, you can't deny that the documentation for the Java API is fantastic. Is there any similarly complete docs for the Python standard libraries? I've looked at the official docs and read through Dive into Python, but when I look up, say, lists on either one, I just get a handful of functions and examples of their use. Something like this page is pretty handy, yes, but when I want documentation, I want it to look like this.

Sorry if this is a repeated question, but nothing in the OP seemed to do what I need, least of all the official documentation.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
Try opening an interactive Python interpreter and typing "help(list)" and "help(list.append)".

zero knowledge
Apr 27, 2008
Ah, that's great. Thanks very much!

Scaevolus
Apr 16, 2007

Spazmo posted:

Ah, that's great. Thanks very much!

If you like printed documentation, Python in a Nutshell is good, although there will probably be another edition out soon, with the release of Py3k.

deedee megadoodoo
Sep 28, 2000
Two roads diverged in a wood, and I, I took the one to Flavortown, and that has made all the difference.


Spazmo posted:

Ah, that's great. Thanks very much!

Also try http://docs.python.org/lib/lib.html and http://docs.python.org/modindex.html

StonedogJones
Mar 13, 2006
I have just taken up a new position as a (mostly)MS based sys admin. I am looking after about 400 servers (once again, mostly MS based). I dont know scripting at all, and I am not even sure how useful it would be to me, other than hearing/reading lots of folks talk about scripting.

I have not ever used a programming language. I did teach myself T-SQL and really enjoyed it, and got reasonably proficient at it, if it matters.

I am wondering if Python would be a good starting point to learn scripting and programming in general? From what I have read it seems like it would, are there any useful books you guys would recommend to an absolute beginner at this?

Wulfeh
Dec 1, 2005

The mmo worth playing: DAoC
Are there any seasoned python programmers out there that wouldn't mind someone asking questions occasionally on AIM or MSN? I use IRC to find solutions sometimes, but it's easier when you can have a more focused conversation with a person. That's not to say IRC isn't helpful, they are pretty awesome and I love #python.

Anyway, go ahead and throw me your aim/msn in a pm if you'd be willing :shobon:

Bozart
Oct 28, 2006

Give me the finger.

StonedogJones posted:

I have just taken up a new position as a (mostly)MS based sys admin. I am looking after about 400 servers (once again, mostly MS based). I dont know scripting at all, and I am not even sure how useful it would be to me, other than hearing/reading lots of folks talk about scripting.

I have not ever used a programming language. I did teach myself T-SQL and really enjoyed it, and got reasonably proficient at it, if it matters.

I am wondering if Python would be a good starting point to learn scripting and programming in general? From what I have read it seems like it would, are there any useful books you guys would recommend to an absolute beginner at this?

Learning Python is a pretty good beginner book, and leads right into Programming Python, which has almost everything in it that you would need.

However, if it is an MS shop you might also want to look at .NET, particularly C#? I haven't used it at all though.

Scaevolus
Apr 16, 2007

Wulfeh posted:

Are there any seasoned python programmers out there that wouldn't mind someone asking questions occasionally on AIM or MSN? I use IRC to find solutions sometimes, but it's easier when you can have a more focused conversation with a person. That's not to say IRC isn't helpful, they are pretty awesome and I love #python.

Try #cobol@irc.synirc.net -- the conversation is generally slower than #python, so we can spend more time discussing particulars.

Adbot
ADBOT LOVES YOU

clayburn
Mar 6, 2007

Cammy Cam Juice
What would be the most efficient way to print through a list of tuples? I'm new to python, coming from java and love how simple some things are to do, so I'm thinking there is an elegant way to do this. In my mind it would require something like:
code:
for i in list:
   print list[i][0] + '\t' + list[i][1]
This doesn't seem that bad, but I thought I remembered reading something that said to never iterate through a list to print it's elements like that and to use string.join instead.

  • Locked thread