[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

How to automate accessor definition?

kj

3/20/2010 10:16:00 PM







I need to create a class solely for the purpose of encapsulating
a large number of disparate data items. At the moment I have no
plans for any methods for this class other than the bazillion
accessors required to access these various instance variables.
(In case it matters, this class is meant to be a private helper
class internal to a module, and it won't be subclassed.)

What is "best practice" for implementing this sort of class
*succinctly* (i.e. without a lot of repetitive accessor code)?

Also, one more question concerning syntax. Suppose that i represents
an instance of this class. Is it possible to define the class to
support this syntax

val = i.field
i.field += 6

....rather than this one

val = i.get_field()
i.set_field(i.get_field() + 6)

?

TIA!

~K
19 Answers

Chris Rebert

3/20/2010 10:54:00 PM

0

On Sat, Mar 20, 2010 at 3:15 PM, kj <no.email@please.post> wrote:
> I need to create a class solely for the purpose of encapsulating
> a large number of disparate data items.  At the moment I have no
> plans for any methods for this class other than the bazillion
> accessors required to access these various instance variables.
> (In case it matters, this class is meant to be a private helper
> class internal to a module, and it won't be subclassed.)

If it's just a completely dumb struct-like class, you might consider
something like:
http://docs.python.org/library/collections.html#collections....

> What is "best practice" for implementing this sort of class
> *succinctly* (i.e. without a lot of repetitive accessor code)?

Is there any good reason you can't just use straight instance
variables? Python ain't Java; vanilla, boilerplate accessor methods
should almost always be avoided.

> Also, one more question concerning syntax.  Suppose that i represents
> an instance of this class.  Is it possible to define the class to
> support this syntax
>
>  val = i.field
>  i.field += 6
>
> ...rather than this one
>
>  val = i.get_field()
>  i.set_field(i.get_field() + 6)
>
> ?

Yes, using the magic of the property() function:
http://docs.python.org/library/functions.htm...

Cheers,
Chris
--
http://blog.re...

Steven D'Aprano

3/21/2010 2:32:00 AM

0

On Sat, 20 Mar 2010 22:15:54 +0000, kj wrote:

> I need to create a class solely for the purpose of encapsulating a large
> number of disparate data items.

There's a built-in for that. It's called "dict". Syntax for item access
is a tiny bit different, but still very common:

data['foo']

instead of

data.foo

If you need to customize item access, you need to modify __getitem__,
__setitem__ and __delitem__ instead of __getattr__ etc., but otherwise
they are nearly identical. Ignoring a few complications due to slots and
inheritance, attribute access is built on top of item access, so you
won't notice any performance hit (and you might see a tiny performance
benefit).


> At the moment I have no plans for any
> methods for this class other than the bazillion accessors required to
> access these various instance variables.

Huh? If you have instance variables, why don't you refer to them by name?

x = MyClass() # create an instance
y = MyClass() # another variable bound to an instance
z = MyClass() # etc.
print x, y, z



> (In case it matters, this class
> is meant to be a private helper class internal to a module, and it won't
> be subclassed.)
>
> What is "best practice" for implementing this sort of class *succinctly*
> (i.e. without a lot of repetitive accessor code)?

Leave the repetitive accessor code out. Python isn't Java.

http://dirtsimple.org/2004/12/python-is-not...


> Also, one more question concerning syntax. Suppose that i represents an
> instance of this class. Is it possible to define the class to support
> this syntax
>
> val = i.field
> i.field += 6

Classes already support that.


>>> class C(object):
.... pass
....
>>> i = C()
>>> i.field = 42
>>> val = i.field
>>> i.field += 6
>>> print (val, i.field)
42 48



> ...rather than this one
>
> val = i.get_field()
> i.set_field(i.get_field() + 6)
>
> ?

Good grief! No wonder Java coders are so unproductive :(




--
Steven

Diez B. Roggisch

3/21/2010 4:09:00 PM

0

kj <no.email@please.post> wrote:
>
>
>
>
>
>
> I need to create a class solely for the purpose of encapsulating
> a large number of disparate data items. At the moment I have no
> plans for any methods for this class other than the bazillion
> accessors required to access these various instance variables.
> (In case it matters, this class is meant to be a private helper
> class internal to a module, and it won't be subclassed.)
>
> What is "best practice" for implementing this sort of class
> *succinctly* (i.e. without a lot of repetitive accessor code)?
>
> Also, one more question concerning syntax. Suppose that i represents
> an instance of this class. Is it possible to define the class to
> support this syntax
>
> val = i.field
> i.field += 6
>
> ...rather than this one
>
> val = i.get_field()
> i.set_field(i.get_field() + 6)
>
> ?


You don't. Python is not Java. So just use instance attributes, and if
you need bhavior when accessing an attribute, introduce a property.

Diez

kj

3/21/2010 4:58:00 PM

0

In <639908184290880449.447600deets-nospam.web.de@news.hansenet.de> Diez B. Roggisch <deets@nospam.web.de> writes:

>You don't. Python is not Java. So just use instance attributes, and if
>you need bhavior when accessing an attribute, introduce a property.


Just accessing attributes looks a bit dangerous to me, due to bugs
like typing

i.typo = 'foo'

when what you meant is

i.type = 'foo'

I tried fixing this by mucking with __setattr__, but I didn't hit
on a satisfactory solution (basically, I couldn't find a good,
self-maintaining, way to specify the attributes that were OK to
set from those that weren't). Is there anything built-in?

Regarding properties, is there a built-in way to memoize them? For
example, suppose that the value of a property is obtained by parsing
the contents of a file (specified in another instance attribute).
It would make no sense to do this parsing more than once. Is there
a standard idiom for memoizing the value once it is determined for
the first time?

Thanks!

~K

kj

3/21/2010 5:03:00 PM

0

In <mailman.1018.1269125666.23598.python-list@python.org> Chris Rebert <clp2@rebertia.com> writes:

>On Sat, Mar 20, 2010 at 3:15 PM, kj <no.email@please.post> wrote:
>> I need to create a class solely for the purpose of encapsulating
>> a large number of disparate data items. =C2=A0At the moment I have no
>> plans for any methods for this class other than the bazillion
>> accessors required to access these various instance variables.
>> (In case it matters, this class is meant to be a private helper
>> class internal to a module, and it won't be subclassed.)

>If it's just a completely dumb struct-like class, you might consider
>something like:
>http://docs.python.org/library/collections.html#collections....

Very cool. Thanks! The class I have in mind is *almost* that
dumb, but performance is a consideration in this case, which may
rule out namedtuple. But I'm glad to learn about it; there are
many places where I can put them to good use.

~K

Steve Holden

3/21/2010 5:12:00 PM

0

kj wrote:
> In <mailman.1018.1269125666.23598.python-list@python.org> Chris Rebert <clp2@rebertia.com> writes:
>
>> On Sat, Mar 20, 2010 at 3:15 PM, kj <no.email@please.post> wrote:
>>> I need to create a class solely for the purpose of encapsulating
>>> a large number of disparate data items. =C2=A0At the moment I have no
>>> plans for any methods for this class other than the bazillion
>>> accessors required to access these various instance variables.
>>> (In case it matters, this class is meant to be a private helper
>>> class internal to a module, and it won't be subclassed.)
>
>> If it's just a completely dumb struct-like class, you might consider
>> something like:
>> http://docs.python.org/library/collections.html#collections....
>
> Very cool. Thanks! The class I have in mind is *almost* that
> dumb, but performance is a consideration in this case, which may
> rule out namedtuple. But I'm glad to learn about it; there are
> many places where I can put them to good use.
>
You may well find that namedtuple is faster than what you put together
yourself, as the collections module is implemented in C.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
See PyCon Talks from Atlanta 2010 http://pyco...
Holden Web LLC http://www.hold...
UPCOMING EVENTS: http://holdenweb.event...

kj

3/21/2010 5:25:00 PM

0

In <4ba58503$0$27838$c3e8da3@news.astraweb.com> Steven D'Aprano <steve@REMOVE-THIS-cybersource.com.au> writes:

>On Sat, 20 Mar 2010 22:15:54 +0000, kj wrote:

>> I need to create a class solely for the purpose of encapsulating a large
>> number of disparate data items.

>There's a built-in for that. It's called "dict". Syntax for item access
>is a tiny bit different, but still very common:

>data['foo']

>instead of

>data.foo

I find the latter more readable than the former. All those extra
elements (the brackets and the quotes, vs the single dot) add
Perl-like visual noise to the code, IMHO.

And dicts are vulnerable to this sort of bug:

data['typo'] = type(foobar)

Also, AFAIK, initialization of a dictionary is never as simple as

i = myclass(*fields)

But in a sense you're right: aside from these objections,
*functionality-wise* what I'm looking for is not very different
from a dictionary, or a C struct.

>> At the moment I have no plans for any
>> methods for this class other than the bazillion accessors required to
>> access these various instance variables.

>Huh? If you have instance variables, why don't you refer to them by name?

I'm sorry, I used the wrong terminology. I see now that the correct
term is "(instance) attribute", not "instance variable".

>Leave the repetitive accessor code out. Python isn't Java.

>http://dirtsimple.org/2004/12/python-is-not...

Thanks for the link! The bit about "Guido's time machine" is pretty
funny.

~K

Dennis Lee Bieber

3/21/2010 6:08:00 PM

0

On Sun, 21 Mar 2010 16:57:40 +0000 (UTC), kj <no.email@please.post>
declaimed the following in gmane.comp.python.general:

> Just accessing attributes looks a bit dangerous to me, due to bugs
> like typing
>
> i.typo = 'foo'
>
> when what you meant is
>
> i.type = 'foo'
>
> I tried fixing this by mucking with __setattr__, but I didn't hit
> on a satisfactory solution (basically, I couldn't find a good,
> self-maintaining, way to specify the attributes that were OK to
> set from those that weren't). Is there anything built-in?
>
I don't believe it was created for the purpose, but check the
documentation on __slots__() {library ref 3.2.4.4 for Python 2.5}


> Regarding properties, is there a built-in way to memoize them? For
> example, suppose that the value of a property is obtained by parsing
> the contents of a file (specified in another instance attribute).
> It would make no sense to do this parsing more than once. Is there
> a standard idiom for memoizing the value once it is determined for
> the first time?
>
Pickle, Shelve? Maybe in conjunction with SQLite3...

--
Wulfraed Dennis Lee Bieber KD6MOG/AE
wlfraed@ix.netcom.com HTTP://wlfraed.home.netcom.com/

Steven D'Aprano

3/21/2010 6:19:00 PM

0

On Sun, 21 Mar 2010 16:57:40 +0000, kj wrote:

> Just accessing attributes looks a bit dangerous to me, due to bugs like
> typing
>
> i.typo = 'foo'
>
> when what you meant is
>
> i.type = 'foo'

That's the price you pay for using a dynamic language like Python with no
declarations. But honestly, the price isn't very high, particularly if
you use an editor or IDE with auto-completion. I can't think of the last
time I had an error due to the above sort of mistake.

Besides, is that error really so much more likely than this?

i.type = 'fpo'

when you meant 'foo'? The compiler can't protect you from that error, not
in any language.


> I tried fixing this by mucking with __setattr__, but I didn't hit on a
> satisfactory solution (basically, I couldn't find a good,
> self-maintaining, way to specify the attributes that were OK to set from
> those that weren't). Is there anything built-in?

No.

You could abuse __slots__, but it really is abuse: __slots__ are a memory
optimization, not a typo-checker.

In Python 3.x, you can (untested) replace the class __dict__ with a
custom type that has more smarts. At the cost of performance. This
doesn't work in 2.x though, as the class __dict__ is always a regular
dictionary.

Something like this might work, at some minor cost of performance:

# Untested
def __setattr__(self, name, value):
if hasattr(self, name):
super(MyClassName, self).__setattr__(name, value)
else:
raise TypeError('cannot create new attributes')

Then, in your __init__ method, to initialise an attribute use:

self.__dict__['attr'] = value

to bypass the setattr.


Or you can use something like PyChecker or PyLint to analyse your code
and warm about likely typos.

But really, it's not a common form of error. YMMV.



> Regarding properties, is there a built-in way to memoize them? For
> example, suppose that the value of a property is obtained by parsing the
> contents of a file (specified in another instance attribute). It would
> make no sense to do this parsing more than once. Is there a standard
> idiom for memoizing the value once it is determined for the first time?

Google for "Python memoization cookbook". This will get you started:

http://code.activestate.com/reci...

Then just apply the memoize decorator to the property getter.




--
Steven

Christian Heimes

3/21/2010 6:37:00 PM

0

Steve Holden wrote:
> You may well find that namedtuple is faster than what you put together
> yourself, as the collections module is implemented in C.

But namedtuple isn't, Steve. Namedtuple is a class generator that
creates fast and efficient classes.