How to get/set class attributes in Python

K

Kalle Anke

I'm coming to Python from other programming languages. I like to
hide all attributes of a class and to only provide access to them
via methods. Some of these languages allows me to write something
similar to this

int age( )
{
return theAge
}

void age( x : int )
{
theAge = x
}

(I usually do more than this in the methods). I would like to do
something similar in Python, and I've come up with two ways to do
it: The first one uses the ability to use a variable number of
arguments ... not very nice. The other is better and uses
__setattr__ and __getattr__ in this way:

class SuperClass:
def __setattr__( self, attrname, value ):
if attrname == 'somevalue':
self.__dict__['something'] = value
else:
raise AttributeError, attrname

def __str__( self ):
return str(self.something)

class Child( SuperClass ):
def __setattr__( self, attrname, value ):
if attrname == 'funky':
self.__dict__['fun'] = value
else:
SuperClass.__setattr__( self, attrname, value )

def __str__( self ):
return SuperClass.__str__( self ) + ', ' + str(self.fun)

Is this the "Pythonic" way of doing it or should I do it in a different
way or do I have to use setX/getX (shudder)
 
S

Steve Jorgensen

I'm coming to Python from other programming languages. I like to
hide all attributes of a class and to only provide access to them
via methods. Some of these languages allows me to write something
similar to this

int age( )
{
return theAge
}

void age( x : int )
{
theAge = x
}

(I usually do more than this in the methods). I would like to do
something similar in Python, and I've come up with two ways to do
it: The first one uses the ability to use a variable number of
arguments ... not very nice. The other is better and uses
__setattr__ and __getattr__ in this way:

class SuperClass:
def __setattr__( self, attrname, value ):
if attrname == 'somevalue':
self.__dict__['something'] = value
else:
raise AttributeError, attrname

def __str__( self ):
return str(self.something)

class Child( SuperClass ):
def __setattr__( self, attrname, value ):
if attrname == 'funky':
self.__dict__['fun'] = value
else:
SuperClass.__setattr__( self, attrname, value )

def __str__( self ):
return SuperClass.__str__( self ) + ', ' + str(self.fun)

Is this the "Pythonic" way of doing it or should I do it in a different
way or do I have to use setX/getX (shudder)

I'm totally new to Python myself, but my understanding is that
 
T

tiissa

Kalle said:
I'm coming to Python from other programming languages. I like to
hide all attributes of a class and to only provide access to them
via methods. Some of these languages allows me to write something
similar to this

int age( )
{
return theAge
}

void age( x : int )
{
theAge = x
}

(I usually do more than this in the methods).

You can 'hide' you getsetters using a property attribute[1]:
... def __init__(self):
... self.age = 0
... def set_age(self, age):
... print 'set %d' % age
... self.__age = age
... def get_age(self):
... print 'get'
... return self.__age
... age = property(get_age, set_age)
... get
20
[1]http://docs.python.org/lib/built-in-funcs.html
 
S

Steve Jorgensen

....
I'm totally new to Python myself, but my understanding is that
....

Oops - I thought I cancelled that post when I relized I was saying nothing,
but somehow, it got posted.
 
A

alex23

Kalle said:
I'm coming to Python from other programming languages. I like to
hide all attributes of a class and to only provide access to them
via methods.

I'm pretty fond of this format for setting up class properties:

class Klass(object):
def propname():
def fget: pass
def fset: pass
def fdel: pass
def doc: """pass"""
return locals()
propname = property(**propname())

(Replacing 'pass' in the getters & setters et.al with the actual
functionality you want, of course...)

This method minimises the leftover bindings, effectively leaving the
getter/setter methods bound only to the property, ensuring they're only
called when the property is acted upon.

Incidentally, kudos & thanks to whomever I originally stole it from :)

-alex23
 
D

deelan

Kalle said:
I'm coming to Python from other programming languages. I like to
hide all attributes of a class and to only provide access to them
via methods. (...)
Is this the "Pythonic" way of doing it or should I do it in a different
way or do I have to use setX/getX (shudder)

the pythonic way is to use "property" (as others have already explained)
only when is *stricly necessary*. this may clarify things up:

"Python Is Not Java"
<http://dirtsimple.org/2004/12/python-is-not-java.html>

HTH.
 
J

John Machin

Kalle said:
You can 'hide' you getsetters using a property attribute[1]:

[1]http://docs.python.org/lib/built-in-funcs.html


Thanks, this is exactly what I was looking for

OTOH, I beseech you to consider an attitude transplant :)

I.e. put your effort into writing code that allows people to do useful
things, rather than opaque guff full of __blahblah__ that stops them
from doing dopey or evil things they're usually smart enough or
righteous enough not to do anyway.

BTW, what do you think of this:

sys.maxint = -12345

Cheers & HTH,
John
 
K

Kalle Anke

the pythonic way is to use "property" (as others have already explained)
only when is *stricly necessary*. this may clarify things up:

Thanks for the link (although Java was only one of the languages I was
thinking of).

Anyway, I got another "problem" (read: being used to do it like this in other
languages). I'm used to use statically typed languages and for me one of the
advantages is that I can be sure that a parameter is of a certain type. So in
Java I could write

void doSomething( data : SomeClass ){ ... }

and I would be sure at compile time that I would only get SomeClass objects
as parameters into the method.

In learning Python I've understood that I should write code in such a way
that it can handle different data and this is fine with me. But what if I
have a class where different attributes should only have values of a certain
type and everything else is an error.

For example, if I have an class that defines three attributes: first and last
name plus email address. The only valid data types for the first two are
strings and for the last an EmailAddress class.

How should I handle this in Python?

Should I use just don't care (but I'm going to send the data to a database so
I need to ensure that the data is OK)? Should I use 'isinstance' and check
manually? Or should I do something else?

(I've been trying to figure out this and other things but I haven't found
much in books or web sites)

jem
 
K

Kalle Anke

OTOH, I beseech you to consider an attitude transplant :)
;-)

I.e. put your effort into writing code that allows people to do useful
things, rather than opaque guff full of __blahblah__ that stops them
from doing dopey or evil things they're usually smart enough or
righteous enough not to do anyway.

I'm just trying to protect myself from myself :) No, I'm playing around with
different ways of doing things, trying to learn Python and how do things in a
proper "pythonic" way.

In this case I'm going to have a class with some properties that are going to
be stored in a database, I don't want to read all the properties everytime I
recreate the object from the database but I still want to give the impression
that the attributes exists and is available. So my idea was to "hide" the
actual database stuff ...
BTW, what do you think of this:

sys.maxint = -12345

I don't really understand what you're meaning.

jem
 
D

Dan Sommers

In learning Python I've understood that I should write code in such a
way that it can handle different data and this is fine with me. But
what if I have a class where different attributes should only have
values of a certain type and everything else is an error.
For example, if I have an class that defines three attributes: first
and last name plus email address. The only valid data types for the
first two are strings and for the last an EmailAddress class.
How should I handle this in Python?
Should I use just don't care (but I'm going to send the data to a
database so I need to ensure that the data is OK)? Should I use
'isinstance' and check manually? Or should I do something else?

One key phrase here is "duck typing": if it walks like a duck, and
swims like a duck, and quacks like a duck, then it's a duck, or at least
you can assume it's a duck. For example:

def put_something( file_open_for_writing, something ):
file_open_for_writing.write( str( something ) )

I don't care if file_open_for_writing is "really a file," as long it has
a "write" method that writes a string somewhere.

The other key phrase is "we're all adults here": if I import sin from
the math module and pass it a unicode string, I get what I deserve.

In lower-level methods/functions, I usually just assume that parameters
are correct, and let the higher-level code catch any exceptions that
occur becuase it (the higher-level code) messed up and passed the wrong
kind of parameter. For example, UI code *has* to check things that
users type, but once that happens, there's no need for my program to
recheck every parameter on every function call all the way down. Either
everything works, or that same UI code catches and logs a TypeError or
ValueError or KeyError exception and asks the user what to do next.

Regards,
Dan
 
G

George Sakkis

alex23 said:
I'm pretty fond of this format for setting up class properties:

class Klass(object):
def propname():
def fget: pass
def fset: pass
def fdel: pass
def doc: """pass"""
return locals()
propname = property(**propname())

(Replacing 'pass' in the getters & setters et.al with the actual
functionality you want, of course...)

This method minimises the leftover bindings, effectively leaving the
getter/setter methods bound only to the property, ensuring they're only
called when the property is acted upon.

Incidentally, kudos & thanks to whomever I originally stole it from :)

-alex23

And a slight improvement in readability IMHO (for python 2.4+) is the
following recipe:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/410698.
Using the Property decorator, the property declaration above becomes:

class Klass(object):
@Property # <--- the capitalized 'P' is not a typo
def propname():
'''Documentation'''
def fget: pass
def fset: pass
def fdel: pass

The Property decorator peeks automagically the fget, fset, fdel and
__doc__ from the property's locals(), instead of having the property
return locals() explicitly. Also, it doesn't break when the property
defines local variables other than [fget, fset, fdel, doc].

George
 
C

Chris Spencer

Kalle said:
void doSomething( data : SomeClass ){ ... }

and I would be sure at compile time that I would only get SomeClass objects
as parameters into the method.

Being an untyped language, Python does not require you to enforce types.
However, for those that require such functionality, you can get away
with using the "assert" statement. For example, if I wanted to make sure
my function foo was only given instances of class Bar, I'd write
something like:
.... assert isinstance(bar, Bar), "argument is not of type Bar"
.... print "argument must be of type Bar"
....Traceback (most recent call last):
File "<stdin>", line 1, in ?

Chris
 
S

Steven D'Aprano

Being an untyped language, Python does not require you to enforce types.
However, for those that require such functionality, you can get away
with using the "assert" statement.

Assuming that Python isn't executed with the optimize switch, which
disables assert.

$ python -O
Python 2.3.3 (#1, May 7 2004, 10:31:40)
[GCC 3.3.3 20040412 (Red Hat Linux 3.3.3-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
py>
py>
py> def tester(x):
.... assert type(x) == type(0)
.... print "%s is an integer." % x
....
py> tester(3)
'3 is an integer'
py> tester("hello")
'hello is an integer'
 
V

vincent wehren

|
| [snap]
|
| >> sys.maxint = -12345
| >
| > I don't really understand what you're meaning.
|
| He meant None = 1 :>

I'm sure you know that has become a no-no in Python 2.4+ ;)
 
P

Peter Dembinski

vincent wehren said:
|
| [snap]
|
| >> sys.maxint = -12345
| >
| > I don't really understand what you're meaning.
|
| He meant None = 1 :>

I'm sure you know that has become a no-no in Python 2.4+ ;)

Yep. Still waiting for delegalisation of others :>
 
S

Steven D'Aprano

Anyway, I got another "problem" (read: being used to do it like this in other
languages). I'm used to use statically typed languages and for me one of the
advantages is that I can be sure that a parameter is of a certain type. So in
Java I could write

void doSomething( data : SomeClass ){ ... }

and I would be sure at compile time that I would only get SomeClass objects
as parameters into the method.

In learning Python I've understood that I should write code in such a way
that it can handle different data and this is fine with me. But what if I
have a class where different attributes should only have values of a certain
type and everything else is an error.

For example, if I have an class that defines three attributes: first and last
name plus email address. The only valid data types for the first two are
strings and for the last an EmailAddress class.

How should I handle this in Python?

Should I use just don't care (but I'm going to send the data to a database so
I need to ensure that the data is OK)? Should I use 'isinstance' and check
manually? Or should I do something else?

As you have worked out, Python doesn't do automatic type-checking for you.
But if you really do need type-checking, you can do it yourself with
isinstance() and/or type(). It isn't forbidden :)

Or, you can try just coercing the data you have to the type you want. eg
instead of testing to see if obj is an integer, you might do:

try:
obj = int(obj)
except:
raise TypeError("can't convert to integer")
insert_in_database(obj)

This may be appropriate for your application.

Another method that is sometimes useful: you are expecting an instance of
Waterfowl class, but actually you are happy to use duck-typing: if it
looks like a duck, swims like a duck, and quacks like a duck, it is
close-enough to a duck:

def process_waterfowl(duck):
"""do things to an instance of Waterfowl, or equivalent"""
try:
look, swim, quack = duck.look, duck.swim, duck.quack
except AttributeError:
raise TypeError("object is not a waterfowl")
# process any object that has look, swim and quack attributes
# as if it were a waterfowl
duck.look()
duck.swim()
duck.quack()
 
B

Bruno Desthuilliers

Chris Spencer a écrit :
Being an untyped language, Python does not require you to enforce types.

Nope. Python *is* typed. But it doesnt confuse implementation with semantic.
However, for those that require such functionality, you can get away
with using the "assert" statement. For example, if I wanted to make sure
my function foo was only given instances of class Bar, I'd write
something like:

... assert isinstance(bar, Bar), "argument is not of type Bar"
... print "argument must be of type Bar" ...
Traceback (most recent call last):
File "<stdin>", line 1, in ?

And *this* is highly unpythonic. And un-OO too, since it makes foo()
dependant on *class* Bar, when it should most probably be enough that it
only depends on (probably part of) the *interface* of class Bar.

Suppose I want to adapt my own class Baaz so it's compatible with Bar.
Now I *must* make the adapter a subclass of Bar (and then depends on
Bar's *implementation*) when it only needs to expose the same (probably
subset of) interface.

Except for exceptions (please pardon the pun), one most usually don't
have to worry about the real class of an object. In 5 years programming
Python, I only had to check for the type of an object a couple of times,
and each time only for more genericity (I mostly needed to dispatch on
some 'generic types' like string-like, sequence-like, map-like,
numeric-like, callable, and others), and this was never used as a way to
restrict the possible types (exceptions are good enough for this).
 
C

Chris Spencer

Bruno said:
And *this* is highly unpythonic. And un-OO too, since it makes foo()
dependant on *class* Bar, when it should most probably be enough that it
only depends on (probably part of) the *interface* of class Bar.

I was providing the original poster with a simple way to ensure
appropriate type. You can assert whatever aspect you wish. If you want
to ensure compatibility with some other property simply use "assert
blah" subsituting blah for whatever test you wish to perform (e.g.
assert MyInterface.implementedBy(bar) to test for interface implementation).
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top