From: Ethan Furman on 27 Mar 2010 09:34 Jonathan Hartley wrote: > Hey everyone. By coincidence, only yesterday I was wondering about > using classes as a way of labeling a block of code, ie. an lightweight > alternative to defining a function that would only be called from one > location. > > eg. instead of: > > > x = 1 > ((some complex logic)) > y = 2 > > > one might like to name the complex block of logic, just to make it > readable: > > > x = 1 > def account_for_non_square_pixels(x): > ((some complex logic)) > account_for_non_square_pixels() > y = 2 > > > But defining and then calling the function like that is a tad > cumbersome. So I was wondering about: > > > > x = 1 > class account_for_non_square_pixels: > ((some complex logic)) > y = 2 > > > I don't exactly like this, but I think you can see what I'm getting > at. Does this fall down in some way I haven't grasped? Is it as awful > an abuse of 'class' as my intuition suggests it is? Is there a way to > do it better? Both solutions look horrible to me, as both hurt readability. Make your function somewhere else, then call it in the code. Who cares if you only use it once? x = 1 account_for_non_square_pixels() y = 2 Isn't that easier to read? And when you want to (read/change) the complex code, you have an easy place to go to do it. ~Ethan~
From: Terry Reedy on 27 Mar 2010 13:10 On 3/27/2010 7:28 AM, Jonathan Hartley wrote: > On Mar 26, 6:26 pm, Luis M. González<luis...(a)gmail.com> wrote: > But defining and then calling the function like that is a tad > cumbersome. So I was wondering about: > > > > x = 1 > class account_for_non_square_pixels: > ((some complex logic)) > y = 2 > > > I don't exactly like this, but I think you can see what I'm getting > at. Does this fall down in some way I haven't grasped? The assignments within the class are performed within a new local namespace. So moving non-toy code within a class block will typically fail.
From: Patrick Maupin on 27 Mar 2010 14:22 On Mar 27, 12:10 pm, Terry Reedy <tjre...(a)udel.edu> wrote: > On 3/27/2010 7:28 AM, Jonathan Hartley wrote: > > > On Mar 26, 6:26 pm, Luis M. González<luis...(a)gmail.com> wrote: > > But defining and then calling the function like that is a tad > > cumbersome. So I was wondering about: > > > x = 1 > > class account_for_non_square_pixels: > > ((some complex logic)) > > y = 2 > The assignments within the class are performed within > a new local namespace. I could be misunderstanding, but I think that may be the point. When you have what is basically a bunch of linear logic in Python, sometimes it makes sense to break the logic up into separate namespaces, such that you don't pollute the global namespace too badly (which could cause obscure failures due to inadvertently reusing a variable name which is not properly initialized on the second use). As the OP mentioned, functions are typically used for this, but then you have to decide if you are going to put all your functions above all the rest of the code, or in-line, which is where they belong according to the flow. Either decision has drawbacks -- it is jarring to see functions defined in the middle of a code flow, but it requires extra work to page up and down to see code that is logically in the middle of a code flow, but has been moved out to a sub-function somewhere. > So moving non-toy code within a class block > will typically fail. I think, as with moving non-toy code into a function, the point may be to *force* (more obvious) failures when something is screwed up, rather than allowing the silent failures that can easily occur with a large number of only marginally related variables in one big namespace. I have done what (I think) the OP is suggesting in the distant past. I don't know why I don't do it any more -- perhaps it is more of a comfort thing, or maybe I have gotten better at choosing the right abstraction points for the function boundaries so that I don't always need to read the function code when I am reading the code that invokes it. But in any case, I don't personally think that: a = 27 b = 30 class DoMoreComputation: c = a + b d = DoMoreComputation.c is a terrible, ugly thing, although it is not my current preference. Regards, Pat
From: Gregory Ewing on 27 Mar 2010 18:56 Jonathan Hartley wrote: > def account_for_non_square_pixels(x): > ((some complex logic)) > account_for_non_square_pixels() > class account_for_non_square_pixels: > ((some complex logic)) I don't see much advantage -- you're still leaving behind an object that won't be used again. If you're concerned about namespace pollution, there are a couple of ways to clean it up: 1) Delete the function after using it: def account_for_non_square_pixels(x): ... account_for_non_square_pixels() del account_for_non_square_pixels 2) Use __all__ to specify which names you intend to export (doesn't prevent anyone from importing something explicitly, but at least it makes your intention clear, stops irrelevant things appearing in dir() or help(), etc). -- Greg
From: Gregory Ewing on 27 Mar 2010 19:40
kj wrote: > What's the word on using "classes as namespaces"? My only concern would be that classes do magical things with certain types when you retrieve them as attributes (e.g. functions, property descriptors), so you can't use one as a completely general purpose transparent container. But for enum constants and the like this isn't a problem. If you're up for a bit of hackery, the following code tricks the class statement into producing a module instead of a class: from types import ModuleType class MetaNamespace(ModuleType): def __init__(self, name, bases, dict): ModuleType.__init__(self, name) self.__file__ = __file__ self.__dict__.update(dict) Namespace = MetaNamespace.__new__(MetaNamespace) class Foo(Namespace): ford = 42 arthur = 88 print Foo print Foo.__dict__ -- Greg |