From: Ethan Furman on
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
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
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
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
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