OO conventions

S

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
 
A

Alex Martelli

Daniel Nogradi said:
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
 
A

Alex Martelli

Blair P. Houghton said:
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()'
1000000 loops, best of 3: 1.07 usec per loop
helen:~ alex$ python -mtimeit -s'def f(): pass' 'f()'
1000000 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
 
B

Blair P. Houghton

Alex said:
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
 
N

Nicola Musatti

I said:
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
 
F

Fredrik Lundh

Nicola said:
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>
 
D

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

Nicola Musatti

Fredrik said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,283
Messages
2,571,405
Members
48,100
Latest member
Calfin5299

Latest Threads

Top