By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,738 Members | 1,730 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,738 IT Pros & Developers. It's quick & easy.

Automatic Generation of Python Class Files

P: n/a
I was thinking of a way I could make writing Python Class Files a
little less painful. I was considering a Ptyhon script that read a
file with a list of property names and method names and then generated
a skeleton class file.

I was even thinking of automatically generating the shell for doc
strings and epydoc tags.

Is there existing scripts that do something like this? If not, I will
try to come up with something. If I'm sucessful I'll release the code
under the GPL and will report back to the list.

However, I thought I would check here first so that I don't reinvent
the wheel.

Thanks,

Scott Huey

Oct 22 '07 #1
Share this Question
Share on Google+
17 Replies


P: n/a
Sunburned Surveyor a écrit :
I was thinking of a way I could make writing Python Class Files
What's a "Python Class File" ?
a
little less painful.
If you find writing classes in Python "painful", then either you have no
experience with any mainstream language or you are doing something wrong.
I was considering a Ptyhon script that read a
file with a list of property names and method names and then generated
a skeleton class file.
Once again, there's no such thing as a "class file" in Python. A module
usually contains several (classes, functions etc) definitions. And since
there's very few boilerplate code in Python, I don't see what your
system would be good for - directly writing the code will not take much
more time than writing the "file with a list of property names and
method names".

My 2 cents...
Oct 22 '07 #2

P: n/a
On Mon, 22 Oct 2007 11:05:52 -0700, Sunburned Surveyor wrote:
On Oct 22, 10:26 am, "Chris Mellon" <arka...@gmail.comwrote:

You wrote: " can't think of a single reason why you would ever want to
do this,
since your "list of method and property names" would be just as
verbose as just typing the actual python code."

I don't think I understand how this would be the same amount of
typing. Consider the following example that would generate a Monster
class file from an input text file (I only did one property and method
in generated class file.):
Really a "monster class".
Contents of input text file:

[Name]
Fire Breathing Dragon

[Properties]
Strength
Scariness
Endurance

[Methods]
eatMaiden argMaiden
fightKnight argKnight

Generated Python Class File:

def class FireBreathingDragon:

def getStrength(self):
"""
Docstring goes here.

@return
@rtype
"""
return self.strength

def setStrength(self, argStrength):
"""
Docstring goes here.

@param argStrength
@ptype
"""
return self.strength

def eatMaiden(self, argMaiden):
"""
Docstring goes here.

@param argMaiden
@ptype
"""
Okay this could be written as:

class FireBreathingDragon(object):
def __init__(self, strength):
self.strength = strength
self.scariness = scariness
self.endurance = endurance

def eat_maiden(self, maiden):
pass

def fight_knight(self knight):
pass

Even with all the stuff from your input file it's shorter than your
generated class.

I left out the docs because having no docs is as valuable as your stubs if
not even better. This way you at least see that there is no real docs and
tools like `pylint` can point out the missing docs.

There are editors with good template support for the small amount of
boilerplate that's left.

Just in case you want to defend the default getters and setters: read up
on properties, i.e. the `property()` function, and the discussions in this
group about Python not being Java.

Ciao,
Marc 'BlackJack' Rintsch
Oct 22 '07 #3

P: n/a
Sunburned Surveyor wrote:
Contents of input text file:

[Name]
Fire Breathing Dragon

[Properties]
Strength
Scariness
Endurance

[Methods]
eatMaiden argMaiden
fightKnight argKnight

Generated Python Class File:

def class FireBreathingDragon:

def getStrength(self):
"""
Docstring goes here.

@return
@rtype
"""
return self.strength

def setStrength(self, argStrength):
"""
Docstring goes here.

@param argStrength
@ptype
"""
return self.strength

def eatMaiden(self, argMaiden):
"""
Docstring goes here.

@param argMaiden
@ptype
"""
This should instead generate::

# Inherit from object. There's no reason to create old-style classes.
class FireBreathingDragon(object):

# Python is not Java. You don't need getters and setters.
# Use public attributes. If you ever decide later that you
# need different attributes, you can always use property()
# to make your getters and setters look like public attributes
def __init__(self, stregth, scariness, endurance):
self.strength = strength
self.scariness = scariness
self.endurance = endurance
STeVe
Oct 22 '07 #4

P: n/a
You wrote: " can't think of a single reason why you would ever want to
do this,
since your "list of method and property names" would be just as
verbose as just typing the actual python code."

I don't think I understand how this would be the same amount of
typing. Consider the following example that would generate a Monster
class file from an input text file (I only did one property and method
in generated class file.):

Contents of input text file:

[Name]
Fire Breathing Dragon

[Properties]
Strength
Scariness
Endurance

[Methods]
eatMaiden argMaiden
fightKnight argKnight
Others have already given you reasons why that is a bad idea. Another
one is this: how do you deal with changes to your generated classfile?
It's complicated to ensure that you don't override modified code with
generated.

Diez
Oct 22 '07 #5

P: n/a
On Oct 22, 11:43 am, Steven Bethard <steven.beth...@gmail.comwrote:
Sunburned Surveyor wrote:
Contents of input text file:
[Name]
Fire Breathing Dragon
[Properties]
Strength
Scariness
Endurance
[Methods]
eatMaiden argMaiden
fightKnight argKnight
Generated Python Class File:
def class FireBreathingDragon:
def getStrength(self):
"""
Docstring goes here.
@return
@rtype
"""
return self.strength
def setStrength(self, argStrength):
"""
Docstring goes here.
@param argStrength
@ptype
"""
return self.strength
def eatMaiden(self, argMaiden):
"""
Docstring goes here.
@param argMaiden
@ptype
"""

This should instead generate::

# Inherit from object. There's no reason to create old-style classes.
class FireBreathingDragon(object):

# Python is not Java. You don't need getters and setters.
# Use public attributes. If you ever decide later that you
# need different attributes, you can always use property()
# to make your getters and setters look like public attributes
def __init__(self, stregth, scariness, endurance):
self.strength = strength
self.scariness = scariness
self.endurance = endurance

STeVe- Hide quoted text -

- Show quoted text -
Thank you for the advice Steve. I didn't know that I should inherit
from Object. I will change my existing Python code accordingly.

Scott Huey

Oct 22 '07 #6

P: n/a
Sunburned Surveyor wrote:
I also intended to add statements creating properties from the getter
and setter methods. I understand that getters and setters aren't
really necessary if you aren't making a property. I just forgot to add
the property statements to my example.
You still don't want to define the getters and setters if they're just
going to set an attribute. Just use an attribute itself.

Java makes you define getters and setters because there's no way to make
method calls look like an attribute access. So in Java if you start
with a public attribute, you can never adjust the API later.

In Python, you can use property() to make method calls look like
attribute access. This could be necessary if you have an existing API
that used public attributes, but changes to your code require those
attributes to do additional calculations now.

But if you're creating a class for the first time, it should *never* use
property(). There's no need to retrofit anything.

STeVe
Oct 22 '07 #7

P: n/a
Steven Bethard a écrit :
(snip)
In Python, you can use property() to make method calls look like
attribute access. This could be necessary if you have an existing API
that used public attributes, but changes to your code require those
attributes to do additional calculations now.

But if you're creating a class for the first time, it should *never* use
property(). There's no need to retrofit anything.
May I kindly disagree here ?-)

Computed attributes are IMHO not only a life-saver when it comes to
refactoring. There are cases where you *really* have - by 'design' I'd
say - the semantic of a property, but know from the start you'll need
computation (for whatever reason). Then what would be the rationale for
using explicit getters/setters ?

Oct 22 '07 #8

P: n/a
On Oct 22, 1:23 pm, Bruno Desthuilliers
<bdesth.quelquech...@free.quelquepart.frwrote:
Steven Bethard a écrit :
(snip)
In Python, you can use property() to make method calls look like
attribute access. This could be necessary if you have an existing API
that used public attributes, but changes to your code require those
attributes to do additional calculations now.
But if you're creating a class for the first time, it should *never* use
property(). There's no need to retrofit anything.

May I kindly disagree here ?-)

Computed attributes are IMHO not only a life-saver when it comes to
refactoring. There are cases where you *really* have - by 'design' I'd
say - the semantic of a property, but know from the start you'll need
computation (for whatever reason). Then what would be the rationale for
using explicit getters/setters ?
Bruno,

Thanks for the detailed response. I need some time to digest what you
wrote. I will read this thread again and think carefully about what
you have saaid.

Scott Huey

Oct 22 '07 #9

P: n/a
On Oct 22, 11:44 am, "Diez B. Roggisch" <de...@nospam.web.dewrote:
You wrote: " can't think of a single reason why you would ever want to
do this,
since your "list of method and property names" would be just as
verbose as just typing the actual python code."
I don't think I understand how this would be the same amount of
typing. Consider the following example that would generate a Monster
class file from an input text file (I only did one property and method
in generated class file.):
Contents of input text file:
[Name]
Fire Breathing Dragon
[Properties]
Strength
Scariness
Endurance
[Methods]
eatMaiden argMaiden
fightKnight argKnight

Others have already given you reasons why that is a bad idea. Another
one is this: how do you deal with changes to your generated classfile?
It's complicated to ensure that you don't override modified code with
generated.

Diez- Hide quoted text -

- Show quoted text -
Diez,

I didn't realize all of the shortcomings with my example until the
others responded. I was just trying to save myself some typing, but I
realize know the problem was my lack of understanding Python syntax.

I will consider myself schooled! :]

Scott Huey

Oct 22 '07 #10

P: n/a
On Mon, 22 Oct 2007 17:31:51 -0600, Steven Bethard wrote:
Bruno Desthuilliers wrote:
>Computed attributes are IMHO not only a life-saver when it comes to
refactoring. There are cases where you *really* have - by 'design' I'd
say - the semantic of a property, but know from the start you'll need
computation (for whatever reason). Then what would be the rationale for
using explicit getters/setters ?

I'd be interested to hear what these use cases are.
Stupid little example: A circle object with `radius` and `diameter`
attributes. It doesn't make sense to store both a as normal attributes
because they will eventually get out of sync. One can be implemented as a
property.

Another one is delegation of attribute access. I'm thinking of a wrapper
class around an object with an attribute, say `is_active`, and a wrapper
that has a property with the same name that returns the value of the
wrapped objects attribute.

Or lazy computation of an attribute. Breaks expectations for the first
access -- long calculation for simple attribute access -- but meets it for
every subsequent access.

Ciao,
Marc 'BlackJack' Rintsch
Oct 23 '07 #11

P: n/a
Marc 'BlackJack' Rintsch wrote:
On Mon, 22 Oct 2007 17:31:51 -0600, Steven Bethard wrote:
>Bruno Desthuilliers wrote:
>>Computed attributes are IMHO not only a life-saver when it comes to
refactoring. There are cases where you *really* have - by 'design' I'd
say - the semantic of a property, but know from the start you'll need
computation (for whatever reason). Then what would be the rationale for
using explicit getters/setters ?
I'd be interested to hear what these use cases are.

Stupid little example: A circle object with `radius` and `diameter`
attributes. It doesn't make sense to store both a as normal attributes
because they will eventually get out of sync. One can be implemented as a
property.
Could be. But I'd tend to define a get_diameter() method here. As a
user of your class, I'd like to know which one is doing the computation.
What if I'm using ridiculously large ints, and I care about the
multiplication?
Another one is delegation of attribute access. I'm thinking of a wrapper
class around an object with an attribute, say `is_active`, and a wrapper
that has a property with the same name that returns the value of the
wrapped objects attribute.
This is retrofitting to an API, so it already falls under the only time
I think you *should* be using property(). Although in this case, it
might be that __getattr__ is more appropriate.
Or lazy computation of an attribute. Breaks expectations for the first
access -- long calculation for simple attribute access -- but meets it for
every subsequent access.
There are descriptors better than property() at achieving this behavior.
See for example:

http://aspn.activestate.com/ASPN/Coo.../Recipe/363602

My personal experience is that every time I write stuff this way (and I
have many times), I end up re-writing it later as a method because it's
less confusing for a method to take a long time than it is for an
attribute access.

STeVe
Oct 23 '07 #12

P: n/a
On Oct 22, 6:43 pm, Steven Bethard <steven.beth...@gmail.comwrote:
Sunburned Surveyor wrote:
Contents of input text file:
[Name]
Fire Breathing Dragon
[Properties]
Strength
Scariness
Endurance
[Methods]
eatMaiden argMaiden
fightKnight argKnight
Generated Python Class File:
def class FireBreathingDragon:
def getStrength(self):
"""
Docstring goes here.
@return
@rtype
"""
return self.strength
def setStrength(self, argStrength):
"""
Docstring goes here.
@param argStrength
@ptype
"""
return self.strength
def eatMaiden(self, argMaiden):
"""
Docstring goes here.
@param argMaiden
@ptype
"""

This should instead generate::

# Inherit from object. There's no reason to create old-style classes.

We recently had to change an object pipeline from new style classes to
old style. A lot of these objects were being created and the *extra
overhead* of new style classes was killing us. :-)

Michael
http://www.manning.com/foord

Oct 29 '07 #13

P: n/a
Fuzzyman wrote:
On Oct 22, 6:43 pm, Steven Bethard <steven.beth...@gmail.comwrote:
># Inherit from object. There's no reason to create old-style classes.

We recently had to change an object pipeline from new style classes to
old style. A lot of these objects were being created and the *extra
overhead* of new style classes was killing us. :-)
I'm curious. Was it memory or speed overhead that was the problem?

Steve
Oct 29 '07 #14

P: n/a
Fuzzyman a écrit :
On Oct 22, 6:43 pm, Steven Bethard <steven.beth...@gmail.comwrote:
(snip)
># Inherit from object. There's no reason to create old-style classes.


We recently had to change an object pipeline from new style classes to
old style. A lot of these objects were being created and the *extra
overhead* of new style classes was killing us. :-)
Maybe a dumb question, but what about __slots__ here ? (NB : never faced
this kind of problem myself).
Oct 30 '07 #15

P: n/a
Fuzzyman <fu******@gmail.comwrites:
We recently had to change an object pipeline from new style classes
to old style. A lot of these objects were being created and the
*extra overhead* of new style classes was killing us. :-)
Can you please expand on this? What extra overhead of new-style
classes are you referring to?

Memory overhead seems to firmly favor new-style classes, especially
for small object. A trivial small-object allocation test such as

# After running this, use "top" or "ps" to see the ballpark memory
# consumption. Remove "(object)" to measure for old-style class.
python -c 'import time
class A(object): pass
l=[A() for n in xrange(2000000)]
time.sleep(100)'

shows the Python process growing to 78M with a new-style class and to
354M with an old-style class. And that is without even starting to
use actual optimizations, such as using __slots__! Instantiation time
difference is less drastic, but still shows significant improvement
with the use of new-style classes: 0.27 usec for new-style, 0.40 usec
old-style (measured with timeit, subtracted baseline overhead).
Oct 30 '07 #16

P: n/a
On Oct 29, 11:35 pm, Steven Bethard <steven.beth...@gmail.comwrote:
Fuzzyman wrote:
On Oct 22, 6:43 pm, Steven Bethard <steven.beth...@gmail.comwrote:
# Inherit from object. There's no reason to create old-style classes.
We recently had to change an object pipeline from new style classes to
old style. A lot of these objects were being created and the *extra
overhead* of new style classes was killing us. :-)

I'm curious. Was it memory or speed overhead that was the problem?

It was speed overhead - I have to add a disclaimer that this is
IronPython, but my understanding is that the situation is similar with
CPython. Creating new style class instances is slower than for old
style classes.

This was in the execution of spreadsheets, where we had a pipeline of
three objects for each spreadsheet element (not sure if the
implementation is still the same now).

Michael
http://www.manning.com/foord

>
Steve

Oct 30 '07 #17

P: n/a
On Oct 30, 2007 5:52 AM, Fuzzyman <fu******@gmail.comwrote:
On Oct 29, 11:35 pm, Steven Bethard <steven.beth...@gmail.comwrote:
Fuzzyman wrote:
On Oct 22, 6:43 pm, Steven Bethard <steven.beth...@gmail.comwrote:
># Inherit from object. There's no reason to create old-style classes.
We recently had to change an object pipeline from new style classes to
old style. A lot of these objects were being created and the *extra
overhead* of new style classes was killing us. :-)
I'm curious. Was it memory or speed overhead that was the problem?


It was speed overhead - I have to add a disclaimer that this is
IronPython, but my understanding is that the situation is similar with
CPython. Creating new style class instances is slower than for old
style classes.
The obvious timeit test shows new-style classes being created in half
the time of old style ones. I certainly would not generalize to
CPython from IronPythons performance characteristics, especially with
something that's so dependent on both the .NET runtime and on the
details of IronPython integration as object creation.

C:\>python -m timeit -s "class C: pass" "c = C()"
1000000 loops, best of 3: 0.315 usec per loop

C:\>python -m timeit -s "class C(object): pass" "c = C()"
10000000 loops, best of 3: 0.175 usec per loop
Oct 30 '07 #18

This discussion thread is closed

Replies have been disabled for this discussion.