Re: OO conventions

2006-02-06 Thread Nicola Musatti

I V wrote:
 Nicola Musatti wrote:
[...]
  Factory functions (or classes) are there to solve this problem and
  still allow a clean separation of concerns. Although instances of Klass
  are created uninitialized, they only live in this state within their
  factory and only reach trhe outside world only when they are in a
  usable state.

 This may be my limited imagination, but I can't think of a situation
 when you would prefer something like:

 def factory(info):
 k = Klass()
 data = get_initial_data(info)
 k.set_data(data)
 return k

 to:

 def factory(info):
 data = get_initial_data(info)
 return Klass(data)

 What would be the value of doing the initialization in a separate
 method, rather than the constructor?

I didn't express my intent clearly. I agree that in general your second
example is to be preferred to the first one. In fact the only reason I
could think of using the first scheme is when the second would lead to
Klass's __init__ method having a large number of parameters.

What is important to me is to keep your get_initial_data() function
outside Klass if it's task is non trivial, e.g. it has to interact with
the OS or a DB.

Cheers,
Nicola Musatti

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-06 Thread Fredrik Lundh
Nicola Musatti wrote:

  def factory(info):
  k = Klass()
  data = get_initial_data(info)
  k.set_data(data)
  return k
 
  to:
 
  def factory(info):
  data = get_initial_data(info)
  return Klass(data)
 
  What would be the value of doing the initialization in a separate
  method, rather than the constructor?

 I didn't express my intent clearly. I agree that in general your second
 example is to be preferred to the first one. In fact the only reason I
 could think of using the first scheme is when the second would lead to
 Klass's __init__ method having a large number of parameters.

 What is important to me is to keep your get_initial_data() function
 outside Klass if it's task is non trivial, e.g. it has to interact with
 the OS or a DB.

why ?

/F



-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-06 Thread Daniel Nogradi
  So after all, what is a 'factory' or 'factory function'?

 A brief explanation in Python terms is at
 http://www.aleax.it/ep03_pydp.pdf -- pages (slides) 37-44 (the rest of
 the presentation is about an even more fundamental design pattern,
 template method).  A far more extensive essay can be found, for
 example, at
 http://gsraj.tripod.com/design/creational/factory/factory.html -- it
 names the pattern factory method, not factory function (method is
 probably a more widespread name for it) and presents examples in Java
 and Corba IDL.

 Anyway, trying to summarize:

 - what: any function or method or other callable whose task it
 is to build and return new objects can be called a factory;

 - sometimes a factory may get away with returning an existing
 object for recycling as if it was a new one, saving some
 resources, and this is one advantage;

 - a factory may choose what exact type of object to build and return
 based on arguments or other circumstances, and this is a second
 advantage.

 Program to an interface, not to an implementation -- the key
 underlying principle ot the gang of 4's Design Patterns book.

 If you build an object of a specific given type (new Foo in Java
 or C++), you're hardwiring the choice of implementation (the
 exact concrete type); delegating the building to a method or
 function frees your application from such hardwiring and lets
 it be concentrated (if needed at all) in one spot (the factory).
 [[With the registry pattern you may even be able to remove
 any hardwiring, but that's a pretty advanced and subtle idea]].


 Alex

Thank you very much, this helped a lot. Just one side note, the url
http://www.aleax.it/ep03_pydp.pdf should be
http://www.aleax.it/Python/ep03_pydp.pdf, I found your document there.
Thanks again.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-06 Thread Scott David Daniels
Fredrik Lundh wrote:
 Nicola Musatti wrote:
 What is important to me is to keep your get_initial_data() function
 outside Klass if it's task is non trivial, e.g. it has to interact with
 the OS or a DB.
 
 why ?

In order to simplify testing.

--Scott David Daniels
[EMAIL PROTECTED]
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-06 Thread Nicola Musatti

Fredrik Lundh wrote:
 Nicola Musatti wrote:
[...]
  What is important to me is to keep your get_initial_data() function
  outside Klass if it's task is non trivial, e.g. it has to interact with
  the OS or a DB.

 why ?

Separating the internal logic of an application from its interactions
with the outside world, e.g. retrieval from a file or a database and
presentation to a GUI, makes it easier to reuse the logic in different
contexts and may help make it possible to use highly generic solutions
for those interactions. I'm thinking of code generation or
introspection, which may be applied with very limited knowledge of the
application logic.

In larger projects I find that this separation tends to match the
different areas of expertise that are needed: database experts, GUI
experts, domain experts, etc.

Cheers,
Nicola Musatti

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-05 Thread Blair P. Houghton

Alex Martelli wrote:
 As you see, static methods have a small extra lookup cost (a couple
 hundred nanoseconds on my oldish laptop);

I would've expected the opposite effect...I guess the runtime
considers instances more active than the static portion of
a class.

 Premature
 optimization is the root of all evil in programming, as Knuth wrote
 quoting Hoare -- and anybody who's read Knuth's work knows he is
 anything BUT indifferent to real optimization; the key is avoiding that
 premature part!-)

Apropos of which someone mentioned in a thread on Slashdot
today about writing an entire program's code in Python first and
then optimizing portions to C or C++ only as performance warrants.

Seems like a good idea.  I've noticed Python is a lot easier to
get up-and-running with, even if you're as unfamiliar with it as
I am, compared to the other two.

--Blair

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-04 Thread Daniel Nogradi
  Actually, this way of creating a class instance is good OO practice in
  many places: The Image.open() method acts as a factory-function for
  creating Image objects.
  You don't know, until you inspect the return value, if the created
  object is actually an instance of class Image or something which just
  happens to behave like one...
  It could for instance be a sub-class of Image, JpegImage, if that
  better suits the class library designers.
  In general, factory-functions allow greater uncoupling between
  interface and implementation.
 

 From all the enlightening replies it seems to me that my next task
 should be to look into what 'factory functions' are. Whenever I've
 seen the word 'factory' I just skipped it, knowing that if I really
 need to know what it is, I'll come back to it later. Apparently it's
 just about time, thanks all for the comments.



I've been looking around for what factory functions are, but honestly
I've been grepping and googling but couldn't find a clear definition
of the concept of 'factory', 'factory function' or 'class factory'. As
I've said I'm relatively new to OOP and the reason is that for too
long I thought that there is no need for it, ordinary C will do. But
once the concepts became clear, it started to become useful. That's
why I'm not particularly interested in examples and code snippets but
rather the general ideas and their definitions, but for these
'factories' I really couldn't find a clear explanation anywhere only
how to use them, example code and such. Perhaps because I was only
searching in the context of Python.

So after all, what is a 'factory' or 'factory function'?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-04 Thread Steve Holden
Daniel Nogradi wrote:
[...]
 So after all, what is a 'factory' or 'factory function'?

The name is intended to be indicative: it's a function that makes things 
- usually instances of some class.

As has already been pointed out. Image is a module from PIL, so 
Image.open() is a function in that module. When you call it, it creates 
an instance of some suitable image class (which will depend on the type 
of the image) and returns that.

The point here is that Image.open() returns a 
JpegImagePlugin.JpegImageFile instance for a .jpg file, a 
GifImagePlugin.GifImageFile instance for a .gif file, and so on. It 
wouldn't make sense to use a single class to represent all these 
different image types, so Image.open() just creates an instance of the 
appropriate class (whatever that may be, which will vary from call to 
call) and returns that.

regards
  Steve
-- 
Steve Holden   +44 150 684 7255  +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006  www.python.org/pycon/

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-04 Thread Alex Martelli
Daniel Nogradi [EMAIL PROTECTED] wrote:
   ...
 So after all, what is a 'factory' or 'factory function'?

A brief explanation in Python terms is at
http://www.aleax.it/ep03_pydp.pdf -- pages (slides) 37-44 (the rest of
the presentation is about an even more fundamental design pattern,
template method).  A far more extensive essay can be found, for
example, at
http://gsraj.tripod.com/design/creational/factory/factory.html -- it
names the pattern factory method, not factory function (method is
probably a more widespread name for it) and presents examples in Java
and Corba IDL.

Anyway, trying to summarize:

- what: any function or method or other callable whose task it
  is to build and return new objects can be called a factory;

- sometimes a factory may get away with returning an existing
  object for recycling as if it was a new one, saving some
  resources, and this is one advantage;

- a factory may choose what exact type of object to build and return
  based on arguments or other circumstances, and this is a second
  advantage.

Program to an interface, not to an implementation -- the key
underlying principle ot the gang of 4's Design Patterns book.

If you build an object of a specific given type (new Foo in Java
or C++), you're hardwiring the choice of implementation (the
exact concrete type); delegating the building to a method or
function frees your application from such hardwiring and lets
it be concentrated (if needed at all) in one spot (the factory).
[[With the registry pattern you may even be able to remove
any hardwiring, but that's a pretty advanced and subtle idea]].


Alex
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-04 Thread Alex Martelli
Blair P. Houghton [EMAIL PROTECTED] wrote:
   ...
  It is (search for 'staticmethod' and 'classmethod'). But there's not
  much use for 'static methods' in Python - we usually just use plain
  functions ('classmethods' are another beast - much more useful than
  staticmethods)
 
 Does it make any noticeable difference in efficiency, or does nobody
 care much about efficiency in Python?

Some of us do, at few but crucial moments; that's why we have timeit.py
to let you measure the performance of pieces of code you care about.

helen:~ alex$ python -mtimeit -s'class X(object):
   @staticmethod
   def f(): pass
 x=X()' 'x.f()'
100 loops, best of 3: 1.07 usec per loop
helen:~ alex$ python -mtimeit -s'def f(): pass' 'f()'
100 loops, best of 3: 0.727 usec per loop
helen:~ alex$ 

As you see, static methods have a small extra lookup cost (a couple
hundred nanoseconds on my oldish laptop); normally, one would use a
function instead.  But if the body of the function/method did some
significant, the lookup overhead would then matter little; clarity and
organization and simplicity, OTOH, _always_ matter.   Premature
optimization is the root of all evil in programming, as Knuth wrote
quoting Hoare -- and anybody who's read Knuth's work knows he is
anything BUT indifferent to real optimization; the key is avoiding that
premature part!-)


Alex
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-03 Thread Steven D'Aprano
On Thu, 02 Feb 2006 17:00:26 -0800, Blair P. Houghton wrote:

 Image would be a superclass to JPGImage, BMPImage, PNGImage, etc...
 
 But which to use could only be determined AFTER opening the file,
 because file.jpg doesn't have type JPG, it has type string and
 semantic value maybe a jpeg file or maybe something misnamed as a jpeg
 file.

Absolutely.
 
 So Image.open(filename) seems right as a factory function that opens
 the file, figures out what it really is, constructs the appropriate
 subclass object (likely by passing a string to the constructor, e.g.,
 JPGImage(filename)), and returns the object via the superclass type.
 The caller can then either check a flag in the superclass to see what
 type the subclass is, or just assume it's the right type of image for
 the filename extension (or does Python have RTTI? I don't recall if
 I've seen it, yet...).

RTTI = Run Time Type Information, yes?

Objects in Python are strongly typed, if that's what you mean. So if each
image kind (jpeg, tiff, png, etc.) is a subclass, then you can easily use
introspection to find out which subclass it is.



 Though if the filename doesn't match the content, someone should raise
 an exception...

That depends on whether you believe DOS style filename extensions are
significant, or that they are a poor substitute for real metadata.

If you come from Windows land, you might thing the file extension is the
file type. If you come from Linux land, you might think that file
extensions are just a label stuck on the file name as a convenience for
the user. If you come from Macintosh land, especially pre-OS X, you
probably think that file extensions are at best a useful redundancy and at
worst an abomination.

From a UI perspective, an application should never refuse to handle a file
because of a mismatch between the file type contents, the file type
metadata (if any), and the file extension, with one important proviso as
follows. In general, if your application handles (say) both JPEGs and
GIFs, and the user tries to open a JPEG named foo.gif, then the correct
action is to advise the user that the file is actually a JPEG, and
give them the opportunity to open the file anyway.

Whether that is best handed internally by making Image.read() raise an
exception or not is a question for the class designer.

The proviso is, if there are potential security implications of that
mismatch (e.g. an executable file masquerading as a .text file), and the
target audience is technically naive, then I believe it may be appropriate
for the application to refuse to handle the file. Don't let the user shoot
themselves in the foot if they aren't technically sophisticated enough to
realise they are shooting themselves in the foot.


-- 
Steven.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-03 Thread Nicola Musatti

Steven D'Aprano wrote:
[...]
 If a class has a natural, obvious default state (e.g. a mutable string
 class might start off empty, a mutable int class might start off as zero,
 a binary tree might start off as an empty node with no children) then it
 makes sense to initialise the class, then add your data.

 But if the class has no natural default state, then it makes no sense to
 create an empty object with no data, a non-image image so to speak.

I don't think this is all there is to it. Even though a class such as
Image might not have a sensible default, initial state it still might
not be reasonable to burden it with the ability to collect the
information needed to reach such an initial state. To put it it another
way: a car is a car, it isn't a car factory.

 In other words, if you find yourself writing methods like this:

 class Klass:
 def foo(self):
 if self.data is None:
 raise KlassError(Can't foo an uninitialized Klass object.)
 else:
 # do something

Factory functions (or classes) are there to solve this problem and
still allow a clean separation of concerns. Although instances of Klass
are created uninitialized, they only live in this state within their
factory and only reach trhe outside world only when they are in a
usable state.

Cheers,
Nicola Musatti

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-03 Thread bruno at modulix
Blair P. Houghton wrote:

(snip)

 So Image.open(filename) seems right as a factory function that opens
 the file, figures out what it really is, constructs the appropriate
 subclass object (likely by passing a string to the constructor, e.g.,
 JPGImage(filename)), and returns the object via the superclass type.

Why via the superclass type ? returns the object is enough.

 The caller can then either check a flag in the superclass to see what
 type the subclass is,

Why the h... ? We don't care what type it is, as long at it does what we
expect it to do.

 or just assume it's the right type of image

Yes

(snip)
 (or does Python have RTTI?

Much better than 'RTTI'.

 I don't recall if
 I've seen it, yet...).

obj.__class__ is a reference to the class (which is itself an object...)


 Though if the filename doesn't match the content, someone should raise
 an exception...

Why ? filenames and extensions are nothing more than conventions.
Image.open() 's responsability is to create an object of the appropriate
class, period. If *your program* needs to ensure that the image type
matches the filename, it's your problem to check this.

 But this means that Image.open(filename) is a static method of the
 superclass, not requiring instantiation.

AFAIK, it's just a function in the Image module (which is itself an
object - instance of class module - but that's orthogonal).

  Image(string) could easily
 default to assuming string is a filename, doing the same work as
 Image.open(filename), though it would at least partially construct an
 Image instance each time it's called, which isn't what you want.
 Image.open(filename) defined as a static method (wait...is that
 possible in Python? I hate being the newbie) 

It is (search for 'staticmethod' and 'classmethod'). But there's not
much use for 'static methods' in Python - we usually just use plain
functions ('classmethods' are another beast - much more useful than
staticmethods)


-- 
bruno desthuilliers
python -c print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in '[EMAIL PROTECTED]'.split('@')])
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-03 Thread I V
Nicola Musatti wrote:
 I don't think this is all there is to it. Even though a class such as
 Image might not have a sensible default, initial state it still might
 not be reasonable to burden it with the ability to collect the
 information needed to reach such an initial state. To put it it another
 way: a car is a car, it isn't a car factory.

What's the burden, though? Surely the only burden is that the class
needs to take the relevant parameters to its __init__ method, which is
no more of a burden than providing some other initialization method
that takes the relevant parameters.

 Factory functions (or classes) are there to solve this problem and
 still allow a clean separation of concerns. Although instances of Klass
 are created uninitialized, they only live in this state within their
 factory and only reach trhe outside world only when they are in a
 usable state.

This may be my limited imagination, but I can't think of a situation
when you would prefer something like:

def factory(info):
k = Klass()
data = get_initial_data(info)
k.set_data(data)
return k

to:

def factory(info):
data = get_initial_data(info)
return Klass(data)

What would be the value of doing the initialization in a separate
method, rather than the constructor?

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-03 Thread Blair P. Houghton

bruno at modulix wrote:
 Blair P. Houghton wrote:
  So Image.open(filename) seems right as a factory function that opens
  the file, figures out what it really is, constructs the appropriate
  subclass object (likely by passing a string to the constructor, e.g.,
  JPGImage(filename)), and returns the object via the superclass type.

 Why via the superclass type ? returns the object is enough.

I'm just being pedantic; because we can't tell from the return
type what subclass type it is, we see it as an object of the
superclass type and then ask it what subclass type it is.

  The caller can then either check a flag in the superclass to see what
  type the subclass is,

 Why the h... ? We don't care what type it is, as long at it does what we
 expect it to do.

We might want to know what to expect.  A function returning a Person
may return a Man or a Woman,.  It could make a difference to our
Libido, so it's in our best interest to find out what was returned, so
we
can call the right methods specific to that subclass.

  or just assume it's the right type of image

 Yes

 (snip)
  (or does Python have RTTI?

 Much better than 'RTTI'.

  I don't recall if
  I've seen it, yet...).

 obj.__class__ is a reference to the class (which is itself an object...)

Shortly after I posted that I came across other posts mentioning
__class__
and I'm trying to grok it in fullness now.

  Though if the filename doesn't match the content, someone should raise
  an exception...

 Why ? filenames and extensions are nothing more than conventions.

Ostensibly.  But they're also a means of deceiving people, so the
handling
of a mismatch deserves care.  Whether that care takes the form of an
exception or by defensive coding (which is kind of what exceptions
simplify) is up to you.

   Image(string) could easily
  default to assuming string is a filename, doing the same work as
  Image.open(filename), though it would at least partially construct an
  Image instance each time it's called, which isn't what you want.
  Image.open(filename) defined as a static method (wait...is that
  possible in Python? I hate being the newbie)

 It is (search for 'staticmethod' and 'classmethod'). But there's not
 much use for 'static methods' in Python - we usually just use plain
 functions ('classmethods' are another beast - much more useful than
 staticmethods)

Does it make any noticeable difference in efficiency, or does nobody
care much about efficiency in Python?

--Blair

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-02 Thread Steven D'Aprano
On Wed, 01 Feb 2006 23:40:37 +0100, Daniel Nogradi wrote:

 I'm relatively new to object oriented programming, so get confused
 about its usage once in a while. Suppose there is a class Image that
 has a number of methods, rotate, open, verify, read, close, etc. Then
 to use this class my natural guess would be to have something like
 
 image = Image( )

Now you have an image object. What is it?

Answer: it isn't an image at all, not in the plain English sense. (Or if
it is, it is an arbitrary default image picked by the class designer.)

 image.read( myfile.jpg )

And now, at long last, the image object actually is an image. So why make
this a two step process? Whatever the Image() initialization does, why
can't it be done automatically when you read the file?

[snip]

 Perhaps the real Image class of PIL doesn't have these methods exactly,
 but doesn't matter, my point is the way it works. Is it normal that
 instead of first creating an instance of a class, it starts right away
 with one its methods? I of course understand that the PIL people simply
 made a choice that their module works this way, period, but I'm just
 wondering if it wouldn't have been more logical to do it along the way
 of my first example.

It seems to me that the choice depends on the data you are handling, plus
of course the class designer's choice. (Dare I say it, whim.)

If a class has a natural, obvious default state (e.g. a mutable string
class might start off empty, a mutable int class might start off as zero,
a binary tree might start off as an empty node with no children) then it
makes sense to initialise the class, then add your data.

But if the class has no natural default state, then it makes no sense to
create an empty object with no data, a non-image image so to speak.

In other words, if you find yourself writing methods like this:

class Klass:
def foo(self):
if self.data is None:
raise KlassError(Can't foo an uninitialized Klass object.)
else:
# do something

then you are just doing pointless make-work to fit a convention that
doesn't make sense for your class. 



-- 
Steven.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-02 Thread Tim N. van der Leeuw

Daniel Nogradi wrote:
 
  In this case, Image seems to be a python module, with the open function
  defined, PIL's Image is not a class.
 

 Thanks for the enlightening remarks, especially this last one, indeed,
 it's not a class.

Actually, this way of creating a class instance is good OO practice in
many places: The Image.open() method acts as a factory-function for
creating Image objects.
You don't know, until you inspect the return value, if the created
object is actually an instance of class Image or something which just
happens to behave like one...
It could for instance be a sub-class of Image, JpegImage, if that
better suits the class library designers.
In general, factory-functions allow greater uncoupling between
interface and implementation.

Regards,

--Tim

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-02 Thread Alex Martelli
Steven D'Aprano [EMAIL PROTECTED] wrote:
  image = Image( )
 
 Now you have an image object. What is it?
 
 Answer: it isn't an image at all, not in the plain English sense. (Or if
 it is, it is an arbitrary default image picked by the class designer.)

No doubt (presumably some kind of as-yet blank one).

  image.read( myfile.jpg )
 
 And now, at long last, the image object actually is an image. So why make
 this a two step process? Whatever the Image() initialization does, why
 can't it be done automatically when you read the file?

Two-step construct (2SC) is a reasonably well-known and widely
useful idiom, and it can serve several kinds of purposes, many but not
all of which are tied to persistence.  For example, to some extent it's
used in Entity Enterprise Javabeans (EJBs): with CMP, instead of having
to create a separate object each time you need a new record from the
database, the container can juggle a pool of objects and reuse each of
them to hold different records at different times, so the number of
beans needed is the number of different records you need to have
_simultaneously_.  The thread pool concept can be implemented in a
similar way, although this is less common.  Another field where 2SC is
often used is GUIs; in that case the main motivation is impedence
matching between a GUI toolkit (often a cross-platform one) and a given
platform's underlying toolkit.

Python offers good opportunities to implement 2SC under the covers
thanks to the split between __new__ and __init__: indeed one can get
tricky, since __new__ need not necessarily perform the first step of 2SC
(it might well return a scrubbed object from the pool rather than the
new one).  Unpickling may normally use __setstate__ instead of __init__
(after __new__, anyway) -- that's more flexible and often easier to
arrange than going through getinitargs (which doesn't work for newstyle
classes anyway) or getnewargs (which doesn't work for classic ones).

Of course, the way OOP is normally taught, 2SC sounds like a heresy, but
out in the real world it does have some advantages (even though
single-step construction remains the normal approach in most cases).

 But if the class has no natural default state, then it makes no sense to
 create an empty object with no data, a non-image image so to speak.

Hmmm, it might, actually; that's what __new__ normally does for
instances of mutable classes, so that __init__ or __setstate__ or other
different methods yet, as appropriate, can then make the object
nonempty in different ways.


 In other words, if you find yourself writing methods like this:
 
 class Klass:
 def foo(self):
 if self.data is None:
 raise KlassError(Can't foo an uninitialized Klass object.)
 else:
 # do something
 
 then you are just doing pointless make-work to fit a convention that
 doesn't make sense for your class. 

It does appear to be a code smell, yes.  But protocol semantics may
often require such constraints as it does not make sense to call x.A
unless x.B has been previously called or viceversa it's forbidden to
call x.A if x.B has already been called, and such constraints are
generally implemented through something like the above idiom.

Consider a file object, for example: after you call f.close() any other
method call must raise an error.  The simplest, most natural way to
implement this is very similar to what you just coded, using a
self.closed flag -- a case of two-step destruction, separating
termination (close) from finalization (destruction proper).

Reusable objects, that can be born scrubbed, loaded with some data and
used for a while, then scrubbed again (with the data getting persisted
off and the object surviving and going into a reuse-pool), typically
need a flag to know if they're scrubbed or not (or, some other data
member may play double duty, e.g. by being None iff an object is
scrubbed).  All normal methods must then raise if called on a scrubbed
object; code for that purpose may be injected by decorators or a custom
metaclass to reduce the boilerplate and code smells.

Note that I'm not defending the OP's contention -- I've seen no reason
in his post making 2SC/2SD desirable.  I'm just addressing the wider
issue... one I probably wouldn't even cover in OOP 101, but hold for a
later course, e.g. one on the architecture of persistence frameworks.


Alex
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-02 Thread Magnus Lycka
Alex Martelli wrote:
 Steven D'Aprano [EMAIL PROTECTED] wrote:
And now, at long last, the image object actually is an image. So why make
this a two step process? Whatever the Image() initialization does, why
can't it be done automatically when you read the file?
 
 Two-step construct (2SC) is a reasonably well-known and widely
 useful idiom, and it can serve several kinds of purposes, many but not
 all of which are tied to persistence. 

I've seen it used as a C++ coding standard when e.g. loading
instances from databases (Person p=Person(); p.init(id);)
since it was considered bad to have code in the constructor
which could throw exceptions. If you make a new Person on
the heap, and catch an exception from the constructor, are
you sure that you delete the object?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-02 Thread Daniel Nogradi
   In this case, Image seems to be a python module, with the open function
   defined, PIL's Image is not a class.
  
 
  Thanks for the enlightening remarks, especially this last one, indeed,
  it's not a class.

 Actually, this way of creating a class instance is good OO practice in
 many places: The Image.open() method acts as a factory-function for
 creating Image objects.
 You don't know, until you inspect the return value, if the created
 object is actually an instance of class Image or something which just
 happens to behave like one...
 It could for instance be a sub-class of Image, JpegImage, if that
 better suits the class library designers.
 In general, factory-functions allow greater uncoupling between
 interface and implementation.


From all the enlightening replies it seems to me that my next task
should be to look into what 'factory functions' are. Whenever I've
seen the word 'factory' I just skipped it, knowing that if I really
need to know what it is, I'll come back to it later. Apparently it's
just about time, thanks all for the comments.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-02 Thread Blair P. Houghton
Image would be a superclass to JPGImage, BMPImage, PNGImage, etc...

But which to use could only be determined AFTER opening the file,
because file.jpg doesn't have type JPG, it has type string and
semantic value maybe a jpeg file or maybe something misnamed as a jpeg
file.

So Image.open(filename) seems right as a factory function that opens
the file, figures out what it really is, constructs the appropriate
subclass object (likely by passing a string to the constructor, e.g.,
JPGImage(filename)), and returns the object via the superclass type.
The caller can then either check a flag in the superclass to see what
type the subclass is, or just assume it's the right type of image for
the filename extension (or does Python have RTTI? I don't recall if
I've seen it, yet...).

Though if the filename doesn't match the content, someone should raise
an exception...

But this means that Image.open(filename) is a static method of the
superclass, not requiring instantiation.  Image(string) could easily
default to assuming string is a filename, doing the same work as
Image.open(filename), though it would at least partially construct an
Image instance each time it's called, which isn't what you want.
Image.open(filename) defined as a static method (wait...is that
possible in Python? I hate being the newbie) would not do any
constructing until after it knew what to construct.

--Blair

-- 
http://mail.python.org/mailman/listinfo/python-list


OO conventions

2006-02-01 Thread Daniel Nogradi
I'm relatively new to object oriented programming, so get confused
about its usage once in a while. Suppose there is a class Image that
has a number of methods, rotate, open, verify, read, close, etc. Then
to use this class my natural guess would be to have something like

image = Image( )
image.read( myfile.jpg )
image.rotate( )
image.close( )

But now it turns out that the PIL module uses this as

image = Image.open( myfile.jpg )
image.verify( )
image.rotate( )
image.close( )

Perhaps the real Image class of PIL doesn't have these methods
exactly, but doesn't matter, my point is the way it works. Is it
normal that instead of first creating an instance of a class, it
starts right away with one its methods? I of course understand that
the PIL people simply made a choice that their module works this way,
period, but I'm just wondering if it wouldn't have been more logical
to do it along the way of my first example.

I guess it's just a matter of convention or how the programmer feels
like, but there are no conventions of this type? Which would be more
pythonic? Or I shouldn't worry and it's totally up to the developer?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-01 Thread Anthony Greene
On Wed, 01 Feb 2006 23:40:37 +0100, Daniel Nogradi wrote:

 I'm relatively new to object oriented programming, so get confused
 about its usage once in a while. Suppose there is a class Image that
 has a number of methods, rotate, open, verify, read, close, etc. Then
 to use this class my natural guess would be to have something like
 
 image = Image( )
 image.read( myfile.jpg )
 image.rotate( )
 image.close( )
 
 But now it turns out that the PIL module uses this as
 
 image = Image.open( myfile.jpg )
 image.verify( )
 image.rotate( )
 image.close( )
 
 Perhaps the real Image class of PIL doesn't have these methods
 exactly, but doesn't matter, my point is the way it works. Is it
 normal that instead of first creating an instance of a class, it
 starts right away with one its methods? I of course understand that
 the PIL people simply made a choice that their module works this way,
 period, but I'm just wondering if it wouldn't have been more logical
 to do it along the way of my first example.
 
 I guess it's just a matter of convention or how the programmer feels
 like, but there are no conventions of this type? Which would be more
 pythonic? Or I shouldn't worry and it's totally up to the developer?


You should take a look at the PIL source files, open() could surely be a
class which takes a filename as an argument at construction time. If you
run across such code, there is really no need to worry, some things are
conventional and some are a matter of preference. In most cases diving
into the source can help clarify a lot of your speculations, better hope
the code is transparent, i hate reading non-readable code. :)

-- 
A wise man knows he knows nothing.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-01 Thread Anthony Greene
On Wed, 01 Feb 2006 23:40:37 +0100, Daniel Nogradi wrote:

 I'm relatively new to object oriented programming, so get confused
 about its usage once in a while. Suppose there is a class Image that
 has a number of methods, rotate, open, verify, read, close, etc. Then
 to use this class my natural guess would be to have something like
 
 image = Image( )
 image.read( myfile.jpg )
 image.rotate( )
 image.close( )
 
 But now it turns out that the PIL module uses this as
 
 image = Image.open( myfile.jpg )
 image.verify( )
 image.rotate( )
 image.close( )
 
 Perhaps the real Image class of PIL doesn't have these methods
 exactly, but doesn't matter, my point is the way it works. Is it
 normal that instead of first creating an instance of a class, it
 starts right away with one its methods? I of course understand that
 the PIL people simply made a choice that their module works this way,
 period, but I'm just wondering if it wouldn't have been more logical
 to do it along the way of my first example.
 
 I guess it's just a matter of convention or how the programmer feels
 like, but there are no conventions of this type? Which would be more
 pythonic? Or I shouldn't worry and it's totally up to the developer?

In this case, Image seems to be a python module, with the open function
defined, PIL's Image is not a class.

-- 
A wise man knows he knows nothing.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-01 Thread Claudio Grondi
Daniel Nogradi wrote:
 I'm relatively new to object oriented programming, so get confused
 about its usage once in a while. Suppose there is a class Image that
 has a number of methods, rotate, open, verify, read, close, etc. Then
 to use this class my natural guess would be to have something like
 
 image = Image( )
 image.read( myfile.jpg )
 image.rotate( )
 image.close( )
 
 But now it turns out that the PIL module uses this as
 
 image = Image.open( myfile.jpg )
 image.verify( )
 image.rotate( )
 image.close( )
 
 Perhaps the real Image class of PIL doesn't have these methods
 exactly, but doesn't matter, my point is the way it works. Is it
 normal that instead of first creating an instance of a class, it
 starts right away with one its methods? I of course understand that
 the PIL people simply made a choice that their module works this way,
 period, but I'm just wondering if it wouldn't have been more logical
 to do it along the way of my first example.
 
 I guess it's just a matter of convention or how the programmer feels
 like, but there are no conventions of this type? Which would be more
 pythonic? Or I shouldn't worry and it's totally up to the developer?
It's probably more up to the context than to the developer.

I can imagine, that the reason for not using
   image = Image()
is, that 'image' would be in a bad defined state suggesting to be an 
Image(), but after image = Image() it were actually not (yet) an image.

It makes sense to me, to have an actual image object with some pixel 
width and height and some color scheme and not only undefined empty 
container for an image. In another context the approach you describe is 
maybe more appropriate, but in case of an Image() object I can't see any 
advantage.

I don't know if there exist any conventions for how to handle such 
matters. For me Pythonic means it should be as I expect it intuitively. 
And my intuition tells me, that I need to define what image I want, when 
I create an Image object.

Maybe it would even be more appropriate to pass the definition of the 
image to the Image class using Image(fileObject) or Image(fileNameSpec) 
or Image(imageFormatAndSizeSpec), but I can imagine, that using 
different methods instead of detection of the type of parameter passed 
is probably less error prone making a good reason supporting the 
approach of using Image.open(bride.jpg) or Image.new(mode, size) for 
creation of an Image object when it is defined in different ways.

As the .new() and .open() methods are anyway there in order to be 
available for further image operations, why not using them directly in 
the process of creating Image() objects?

Claudio
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-01 Thread Kirk McDonald
Daniel Nogradi wrote:
 I'm relatively new to object oriented programming, so get confused
 about its usage once in a while. Suppose there is a class Image that
 has a number of methods, rotate, open, verify, read, close, etc. Then
 to use this class my natural guess would be to have something like
 
 image = Image( )
 image.read( myfile.jpg )
 image.rotate( )
 image.close( )
 
 But now it turns out that the PIL module uses this as
 
 image = Image.open( myfile.jpg )
 image.verify( )
 image.rotate( )
 image.close( )
 
 Perhaps the real Image class of PIL doesn't have these methods
 exactly, but doesn't matter, my point is the way it works. Is it
 normal that instead of first creating an instance of a class, it
 starts right away with one its methods? I of course understand that
 the PIL people simply made a choice that their module works this way,
 period, but I'm just wondering if it wouldn't have been more logical
 to do it along the way of my first example.
 
 I guess it's just a matter of convention or how the programmer feels
 like, but there are no conventions of this type? Which would be more
 pythonic? Or I shouldn't worry and it's totally up to the developer?


If I were coding a class like that, I'd probably do it like this:

image = Image(myfile.jpg)
image.rotate()
image.close()

And, in addition, there would be an image.open() method. In the above, 
__init__ just calls it on its own when the filename is specified.

(Though, of course, I'm not at all familiar with the PIL module; there 
might be more stuff going on behind the scenes with the way they do it.)

-Kirk McDonald
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-01 Thread Daniel Nogradi

 In this case, Image seems to be a python module, with the open function
 defined, PIL's Image is not a class.


Thanks for the enlightening remarks, especially this last one, indeed,
it's not a class.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-01 Thread Terry Hancock
On Wed, 1 Feb 2006 23:40:37 +0100
Daniel Nogradi [EMAIL PROTECTED] wrote:
 I'm relatively new to object oriented programming, so get
 confused about its usage once in a while. Suppose there is
 a class Image that has a number of methods, rotate, open,
 verify, read, close, etc. Then to use this class my
 natural guess would be to have something like
 
 image = Image( )
 image.read( myfile.jpg )
 image.rotate( )
 image.close( )
 
 But now it turns out that the PIL module uses this as
 
 image = Image.open( myfile.jpg )
 image.verify( )
 image.rotate( )
 image.close( )

That's because that *isn't* object oriented.  PIL provides
an open *function* that opens a file containing an image
and *returns* an Image object.  The two Image usages are
not the same. I personally think he should've named the
module Imaging or something, to make this clearer, but you
can of course fix this in the import (I frequently have had
to call it PIL_Image or something, because of collisions
with other modules or objects named Image).

What Lundh is modeling this on is not standard OOP thinking,
but rather the standard way of opening files in Python.

Or you could say he's using a factory function.

I think it is actually not bad style, because in fact, he's
drawing attention to the fact that the image is NOT an
object initialized by the string 'myfile.jpg', but is
rather a function loading data from a file called
'myfile.jpg' and creating a PIL Image object from *that*.

Remember, programming is an art, not a science.
Object-oriented style is a subjective and fuzzy
aesthetic term, and what is most clear depends on what
you've seen before, and what you're trying to be clear
about.

Cheers,
Terry


-- 
Terry Hancock ([EMAIL PROTECTED])
Anansi Spaceworks http://www.AnansiSpaceworks.com

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO conventions

2006-02-01 Thread Fredrik Lundh
Terry Hancock wrote:

 What Lundh is modeling this on is not standard OOP thinking,
 but rather the standard way of opening files in Python.

 Or you could say he's using a factory function.

open is a factory function, and it picks the right class based
on the file you're opening.

anyone arguing that this is bad OOP is deluded.

/F



-- 
http://mail.python.org/mailman/listinfo/python-list