473,396 Members | 1,774 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Confused about properties, descriptors, and attributes...

I've been reading about Python Classes, and I'm a little confused about
how Python stores the state of an object. I was hoping for some help.

I realize that you can't create an empty place holder for a member
variable of a Python object. It has to be given a value when defined,
or set within a method.

But what is the difference between an Attribute of a Class, a
Descriptor in a Class, and a Property in a Class?

If I had a Monster Class, and I wanted to give each Monster a member
variable called ScaryFactor, how would I define it? Does a Property
simply provide methods that access an Attribute?

Thanks,

Scott Huey

P.S. - I'm speaking about the "new" Python classes, not the "old" ones.
I hope my questions make sense.

Apr 20 '06 #1
3 2142
re****************@gmail.com wrote:
But what is the difference between an Attribute of a Class, a
Descriptor in a Class, and a Property in a Class?
A class has a class dictionary, which contains methods and other
class-level members for this class.

Each instance of a class has its own instance dictionary, which holds
the attributes for that instance.

An attribute is an instance variable that lives in the instance dictionary.
if you ask for the attribute value, you get the value from the instance
dictionary. If the attribute is not found in the instance, Python looks
in the class dictionary. If you assign to an attribute, Python adds it
to the instance dictionary.

A descriptor is a special kind of class attribute that implements a
descriptor protocol. if you ask for the attribute value for a descriptor
attribute, or assign to it, Python will ask the descriptor object what
to do.

A property is simply a ready-made descriptor type that maps attribute
access to getter and setter methods.

Still with me?
If I had a Monster Class, and I wanted to give each Monster a member
variable called ScaryFactor, how would I define it?
Assign to it in the initialization method:

class Monster(object):
def __init__(self):
self.ScaryFactor = 100

This gives all monsters their own ScaryFactor value.

Since Python will look in the class dictionary if an attribute is not found
in the instance dictionary, you can also do:

class AltMonster(object):
ScaryFactor = 100

If you do this, all monsters will share the same factor value. However,
if you set the factor on the instance (either by assigning to self inside
a method, or by assigning to it from the outside), that object will get
its own copy.

m1 = AltMonster()
m2 = AltMonster()
m3 = AltMonster()
print m1.ScaryFactor, m2.ScaryFactor, m3.ScaryFactor
# prints 100, 100, 100 (all three refers to the same object)

m1.ScaryFactor = 200
print m1.ScaryFactor, m2.ScaryFactor, m3.ScaryFactor
# prints 200, 100, 100 (m1 has its own attribute value)

Monster.ScaryFactor = 300 # update the class attribute
print m1.ScaryFactor, m2.ScaryFactor, m3.ScaryFactor
# prints 200, 300, 300 (!)
Does a Property simply provide methods that access an Attribute?


It maps attribute accesses to method calls, yes.

You can use it instead of a plain attribute when you need to add getter
or setter logic; there's usually no reason to use properties instead of
attributes for plain data members.

To learn more about descriptors (which are really simple, and rather mind-
boggling), see

http://users.rcn.com/python/download/Descriptor.htm

Hope this helps!

</F>

Apr 20 '06 #2
re****************@gmail.com a écrit :
I've been reading about Python Classes, and I'm a little confused about
how Python stores the state of an object.
Simply put: a Python object is mostly a hashtable, with attribute names
as keys and references to other objects as values - one of these
name/ref pairs pointing to the class object.
I was hoping for some help.

I realize that you can't create an empty place holder for a member
variable of a Python object. It has to be given a value when defined,
or set within a method.
There's a special Python object named None.
But what is the difference between an Attribute of a Class, a
Descriptor in a Class, and a Property in a Class?
Everything is an attribute, one way or another. Let's start simple: an
object has a special attribute named __dict__, in which (references to)
instance attributes - those you set with 'self.attr=val' - are stored.
As I mentioned above, our object has another special attribute named
__class__, that points to the class object - which, being an object,
has itself a __dict__ attribute in which class attributes are stored,
and a __class__ attribute pointing to the metaclass - the class of the
class.

Note BTW that Python functions being objects, the term 'attribute'
include methods... (or more exactly, functions that will be turned into
methods when looked up)

Ok, now how is this used. <overly-simplified> When a name is looked up
on an object (via the lookup operator '.'), it is first looked up in the
object's __dict__. If this fails, it's then looked up in the class's
__dict__, then in parent classes __dict__s. If the attribute object
found is a callable, it is wrapped in a method object before. If the
object is a descriptor (and has been found in a class __dict__), then
the __get__ method of the descriptor is called.</overly-simplified>

NB : a descriptor is an object that implements at least a __get__ method
that takes an instance (the one on which the lookup occurs) and a class
as params. Properties are descriptors. methods too.

The __dict__ of a class is populated with the names and functions
defined in the class: block. The __dict__ of an instance is populated
with the attributes bound to the instance (usually inside method, and
mostly inside the __init__() method, which is called just after object's
creation) - with the exception that, if the name already refers to a
descriptor having a __set__ method, then this will take precedence.

All this is a 1000 feet high, overly simplified view of Python's object
model - the lookup rules are a bit more complex (cf the
__getattr__/__setattr__/__getattribute___ methods, and the complete
definition of the dexcriptor protocol), and I didn't even talked about
slots nor metaclasses.

To summarize: a sample class

class MyObject(object):
classattr = "I am a class attribute"

# the __init__ function will also be
# an attribute of class MyObject
def __init__(self, name):
# _name will be an instance attribute
self._name = name

def _set_name(self, value):
self._name = name
# name will be an attribute of MyClass.
# it's a property - which is a descriptor
name = property(fget=lambda self: self._name, fset=_set_name)
# we don't want to pollute the class's namespace:
del _set_name

and some musing with it:
MyObject.__dict__.keys() ['__module__', 'name', 'classattr', '__dict__', '__weakref__',
'__doc__', '__init__'] MyObject.__dict__['classattr'] 'I am a class attribute' MyObject.__dict__['__init__'] <function __init__ at 0x404134fc> MyObject.__init__ <unbound method MyObject.__init__> MyObject.name <property object at 0x4041661c> MyObject.name.__class__.__dict__.keys() ['fset', '__new__', '__set__', '__getattribute__', '__doc__', 'fget',
'__get__', 'fdel', '__init__', '__delete__'] MyObject.name.__class__.__dict__['fget'] <member 'fget' of 'property' objects> MyObject.name.__class__.fget <member 'fget' of 'property' objects> MyObject.name.fget <function <lambda> at 0x4041356c> MyObject.name.fset <function _set_name at 0x40413534> MyObject.__class__ <type 'type'> m = MyObject('parrot')
m <__main__.MyObject object at 0x40418dcc> m.name 'parrot' MyObject.name.fget(m) 'parrot' dir(m) ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',
'__hash__', '__init__', '__module__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__',
'_name', 'classattr', 'name'] m.__dict__.keys() ['_name'] m.__dict__['_name'] 'parrot' m.classattr 'I am a class attribute' MyObject.classattr 'I am a class attribute' MyObject.classattr = 'yes I am'
m.classattr 'yes I am' m.classattr = "and I am in fact an instance attribute shadowing MyObject.classattr" m.classattr 'and I am in fact an instance attribute shadowing MyObject.classattr' MyObject.classattr 'yes I am' m.__dict__ {'classattr': 'and I am in fact an instance attribute shadowing
MyObject.classattr', '_name': 'parrot'} del m.classattr
m.classattr 'yes I am' def sayHello(obj, who): .... return "hello, %s, my name is %s" % (who, obj.name)
.... sayHello(m, 'Scott') 'hello, Scott, my name is parrot' import types
m.greet = types.MethodType(sayHello, m, m.__class__)
m.greet <bound method MyObject.sayHello of <__main__.MyObject object at 0x40418dcc>> m.__dict__ {'greet': <bound method MyObject.sayHello of <__main__.MyObject object
at 0x40418dcc>>, '_name': 'parrot'} >>> m.greet('Joe') 'hello, Joe, my name is parrot' MyObject.greet Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: type object 'MyObject' has no attribute 'greet'

If I had a Monster Class, and I wanted to give each Monster a member variable called ScaryFactor, how would I define it?
class Monster(object):
def __init__(self, scary_factor):
self.scary_factor = scary_factor

Does a Property
simply provide methods that access an Attribute?
A property is mean to have simple computed attributes. The two main uses
are to restrict access to an existing attribute (ie: make it readonly)
or to compute something from existing attributes. Now you can use custom
descriptors for more advanced computed attributes (that may have nothing
to do with the object on which there are called).

HTH
P.S. - I'm speaking about the "new" Python classes, not the "old" ones.
Hopefully. I don't see much reason to use old-style classes
I hope my questions make sense.


It does. Python's object model is much more complex than it seems at
first sight, and learning how to use it is worth the time spent if you
want to really take advantage of Python's power.

Apr 20 '06 #3
re****************@gmail.com escribió:
I've been reading about Python Classes, and I'm a little confused about
how Python stores the state of an object. I was hoping for some help.

I realize that you can't create an empty place holder for a member
variable of a Python object. It has to be given a value when defined,
or set within a method.
I don't understand what do you mean with "empty place holder". Some
pre-allocated-and-uninitialized memory to hold the attribute value (ala
C++ o java)? Maybe slots?
class Foo(object) : .... __slots__ = ['foo']
.... f=Foo()
dir(f) ['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__',
'__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__slots__', '__str__', 'foo'] f.foo Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: foo f.foo = 3
dir(f) ['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__',
'__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__slots__', '__str__', 'foo'] f.foo 3
But what is the difference between an Attribute of a Class, a
Descriptor in a Class, and a Property in a Class?
I don't know what the formal definitions are. Probably "attribute"
refers to anything that can be obtained by way of getattr(). According
to this "definition" an attribute does not require to be stored in the
instance, it can be calculated or obtained from somewhere else.
class SimpleExample : .... def __getattr__(self, name) :
.... if name=='attr' :
.... return 0
.... raise AttributeError(name)
.... s = SimpleExample()
s.attr 0 s.bar

Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 5, in __getattr__
AttributeError: bar
descriptors are a mechanism/protocol for attribute access. It's intended
to solve some problems of the original __getattr__() protocol.

A property is a specialized type of descriptor which allows
customization of attribute's access methods.
If I had a Monster Class, and I wanted to give each Monster a member
variable called ScaryFactor, how would I define it?
If you're asking when to use plain attributes, descriptors or properties
the answer is that it depends on what you want/need:

* if you store monsters in a database and the ScaryFactor attribute is
computed by some complex and expensive database lookup I'll go for some
kind of lazy descriptor/property

* if you want to be able to control/limit what can be done with an
attribute may be a property is enough. This includes things like make
the attribute read only etc.

* if you don't have special requirements a plain attribute would be
probably simpler and faster

Does a Property
simply provide methods that access an Attribute?


not exactly, it allows you to assign/define the methods that will be
used to access the attribute, but you still access to the attribute in
the usual "dot-way".
For further info take a look at:

http://www.python.org/doc/newstyle/
HTH
Apr 20 '06 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Denis S. Otkidach | last post by:
I've noticed that the order of attribute lookup is inconsistent when descriptor is used. property instance takes precedence of instance attributes: >>> class A(object): .... def...
14
by: Antoon Pardon | last post by:
Can anyone explain why descriptors only work when they are an attribute to an object or class. I think a lot of interesting things one can do with descriptors would be just as interesting if the...
10
by: Martin Miller | last post by:
I'm trying to create some read-only instance specific properties, but the following attempt didn't work: > class Foobar(object): > pass > > foobar = Foobar() > foobar.x =...
3
by: Martin Montgomery | last post by:
I have, for example, a property called myProperty. I would like, when using a property grid to display the property name as "My Property". Is this possible. Is there an attribute etc Thank ...
0
by: Steven Bethard | last post by:
Steven Bethard wrote: > (For anyone else out there reading who doesn't already know this, > Steven D'Aprano's comments are easily explained by noting that the > __get__ method of staticmethod...
4
by: Sarcastic Zombie | last post by:
Code included below. Basically, I've created a series of "question" descriptors, which each hold a managed value. This is so I can implement validation, and render each field into html...
5
by: Bob B. | last post by:
I've been playing with descriptors lately. I'm having one problem I can't seem to find the answer to. I want to assign a descriptor to a list of attributes. I know I should be able to add these...
2
by: Floris Bruynooghe | last post by:
Hi When in a new-style class you can easily transform attributes into descriptors using the property() builtin. However there seems to be no way to achieve something similar on the module...
17
by: David C. Ullrich | last post by:
Having a hard time phrasing this in the form of a question... The other day I saw a thread where someone asked about overrideable properties and nobody offered the advice that properties are...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.