Difference between revisions of "Attribute"

From CS 61A Wiki
Jump to: navigation, search
[checked revision][checked revision]
m ({{Sufficient-class}})
m (copyedit)
Line 1: Line 1:
 
{{Sufficient-class}}
 
{{Sufficient-class}}
 
{{OOP sidebar}}
 
{{OOP sidebar}}
An '''attribute''' of an object is a piece of data that describes the object, stored within the object as a key-value pair. Given an object, one can ask for the value of a particular key using ''dot notation''.
+
An '''attribute''' of an object is a piece of data that describes the object, stored within the object as a key-value pair. Given an object, one can ask for the value of an attribute using ''dot notation''.
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
>>> object.key
+
>>> object.attribute
 
value
 
value
 
</syntaxhighlight>
 
</syntaxhighlight>
To access an object's list of attributes, just call the <code>dir()</code> function on the object.
 
  
== Example of handling attributes ==
+
== List of attributes ==
 +
To access an object's list of attributes, call the <code>dir()</code> function on the object. Example:
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
>>> import datetime
 
>>> import datetime
Line 17: Line 17:
 
2014
 
2014
 
</syntaxhighlight>
 
</syntaxhighlight>
== Class vs. instance attribute ==
 
  
===Class Attribute===
+
===Class attribute===
Attributes defined within a class but outside of methods are class attributes. Class attributes, which include methods, can be accessed by the class or by instances of the class. Class attributes are 'shared' by all instances and the class itself, unless overridden or overwritten by an instance attribute. When a class attribute is changed, all instances and classes that access it will see the change, regardless of what object made the change. Classes that use assignment statements with dot expressions will set a class attribute.
+
Attributes defined within a class but outside of methods are ''class attributes''. Class attributes, which include methods, can be accessed by the class or by instances of the class. Class attributes are 'shared' by all instances and the class itself, unless overridden or overwritten by an instance attribute. When a class attribute is changed, all instances and classes that access it will see the change, regardless of what object made the change. Classes that use assignment statements with dot expressions will set a class attribute.
  
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
Line 45: Line 44:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
===Instance Attribute===
+
==Instance attribute==
Attributes defined inside class methods are instance attributes. Instance attributes are locally defined and can only be accessed by their respective instances. The value of an instance attribute is 'unique' to each instance, and changes to an instance attribute can only be seen by its instance. If a class attribute and instance attribute have the same variable name, then the instance attribute will hide the class attribute. The instance can then only access the instance attribute, although the class can still access the class attribute. Instances that use assignment statements will set instance attributes.
+
Attributes defined inside methods are ''instance attributes''. Instance attributes are locally defined and can only be accessed by their respective instances. The value of an instance attribute is 'unique' to each instance, and changes to an instance attribute can only be seen by its instance. If a class attribute and instance attribute have the same variable name, then the instance attribute will hide the class attribute. The instance can then only access the instance attribute, although the class can still access the class attribute. Instances that use assignment statements will set instance attributes.
  
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
Line 83: Line 82:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Methods ==
+
== Method ==
 
A ''method'' is an attribute of an instance (not of a class) where the value is a function that manipulates the object. Unlike regular functions, methods are ''invoked'' on an object via dot notation, so the object that the method is invoked on will be automatically passed into the method as an argument. Note that accessing the attribute from the class will only return the function, so the object argument must be passed in instead of being omitted via dot notation.
 
A ''method'' is an attribute of an instance (not of a class) where the value is a function that manipulates the object. Unlike regular functions, methods are ''invoked'' on an object via dot notation, so the object that the method is invoked on will be automatically passed into the method as an argument. Note that accessing the attribute from the class will only return the function, so the object argument must be passed in instead of being omitted via dot notation.
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
Line 112: Line 111:
 
6
 
6
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 
== @property ==
 
== @property ==
The property object is, simply put, another way of having a getter and setter method for a defined class. It has three methods a [[Getter|getter]], a [[Setter|setter]], and a deleter (but don't worry about deleters. They are outside the scope of this course and you will not be tested on them.)  
+
The property decorator is another way of having a getter and setter method for a defined class. It has three methods a [[Getter|getter]], a [[Setter|setter]], and a deleter (but don't worry about deleters. They are outside the scope of this course and you will not be tested on them.)  
  
 
Here's an example:
 
Here's an example:
 
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
class ImAClass(object):
 
class ImAClass(object):
Line 178: Line 177:
 
Both of these examples essentially do the same thing in roughly the same amount of code. The advantage of having properties however, is that you may switch from the two whenver you want. Simply add or remove or add the property tags from the getters and setters.
 
Both of these examples essentially do the same thing in roughly the same amount of code. The advantage of having properties however, is that you may switch from the two whenver you want. Simply add or remove or add the property tags from the getters and setters.
  
 +
== AttributeError ==
 +
When one tries to access an attribute of the object that does not exist, Python will raise an <code>AttributeError: 'type_of_obj' object has no attribute 'key'</code>.
  
== AttributeErrors ==
 
When one tries to access an attribute of the object that does not exist, Python will raise an AttributeError: 'type_of_obj' object has no attribute 'key'.
 
 
=== 'Nonetype' has no attribute ===
 
=== 'Nonetype' has no attribute ===
 
This error occurs when the object to the left of the dot notation is <code>None</code>.
 
This error occurs when the object to the left of the dot notation is <code>None</code>.
Line 218: Line 217:
 
         return instance
 
         return instance
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 
== References ==
 
== References ==
 
<references>
 
<references>

Revision as of 13:32, 24 July 2014

An attribute of an object is a piece of data that describes the object, stored within the object as a key-value pair. Given an object, one can ask for the value of an attribute using dot notation.

>>> object.attribute
value

List of attributes

To access an object's list of attributes, call the dir() function on the object. Example:

>>> import datetime
>>> date_object = datetime.date
>>> dir(date_object)
['__add__', '__class__', '__delattr__', '__doc__', '__eq__', ..., 'today', 'toordinal', 'weekday', 'year']
>>> date.year
2014

Class attribute

Attributes defined within a class but outside of methods are class attributes. Class attributes, which include methods, can be accessed by the class or by instances of the class. Class attributes are 'shared' by all instances and the class itself, unless overridden or overwritten by an instance attribute. When a class attribute is changed, all instances and classes that access it will see the change, regardless of what object made the change. Classes that use assignment statements with dot expressions will set a class attribute.

>>> class Test():
        num = 0
        def do_nothing(self):
            return
>>> Test.do_nothing
<function do_nothing at 0x17d6270>
>>> Test.do_nothing = 1
>>> Test.do_nothing
1
>>> inst = Test()
>>> inst.do_nothing()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
>>> inst.do_nothing
1
>>> Test.num
0
>>> inst.num
0

Instance attribute

Attributes defined inside methods are instance attributes. Instance attributes are locally defined and can only be accessed by their respective instances. The value of an instance attribute is 'unique' to each instance, and changes to an instance attribute can only be seen by its instance. If a class attribute and instance attribute have the same variable name, then the instance attribute will hide the class attribute. The instance can then only access the instance attribute, although the class can still access the class attribute. Instances that use assignment statements will set instance attributes.

>>> class Test():
        num = 0
        def __init__(self):
            self.num = 1
        def increase(self):
            self.num += 1
>>> Test.num
0
>>> inst1 = Test()
>>> inst2 = Test()
>>> inst1.num
1
>>> inst2.num
1
>>> inst1.increase()
>>> inst1.num
2
>>> inst2.num
1
>>> class Test():
        char = 'a'
>>> Test.char
'a'
>>> inst = Test()
>>> inst.char
'a'
>>> inst.char = 'b'
>>> inst.char
'b'

Method

A method is an attribute of an instance (not of a class) where the value is a function that manipulates the object. Unlike regular functions, methods are invoked on an object via dot notation, so the object that the method is invoked on will be automatically passed into the method as an argument. Note that accessing the attribute from the class will only return the function, so the object argument must be passed in instead of being omitted via dot notation.

>>> class A():
        def __init__(self, id):
            self.id = id
        def useless_method():
            return 5
        def example_method(self):
            return self.id
>>> a = A(6)
>>> a.useless_method
<bound method A.useless_method of <__main__.A object at 0xe10250>>
>>> a.useless_method()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: useless_method() takes no arguments (1 given)
>>> A.useless_method
<function useless_method at 0xe0ed10>
>>> A.useless_method()
5
>>> a.example_method()
6
>>> b = A(7)
>>> b.example_method()
7
>>> A.example_method(a)
6

@property

The property decorator is another way of having a getter and setter method for a defined class. It has three methods a getter, a setter, and a deleter (but don't worry about deleters. They are outside the scope of this course and you will not be tested on them.)

Here's an example:

class ImAClass(object):
 
    def __init__(self):
        self._Property = None
 
 
    @property
    def Property(self):
        """I am a property."""
        return self._Property
 
 
    @Property.setter
    def Property(self, value):
        self._Property = value
 
 
    @Property.deleter
    def Property(self):
        del self._Property

There is little to no difference between implementing a property vs implementing separate getters and setters, and the difference in the amount of code is often negligible.

Here is an example of implementation using getters and setters[1]:

>>> class Get_set_imp(object):
...   val = 0
...   def setter(self, x):
...       self.val = x
...   def getter(self):
...       return self.val
...
 
>>> x = Get_set_imp()
>>> x.setter(3)
>>> x.getter()
3


And here is the same implementation, this time using properties:

>>> class Prop_imp(object):
...   _val = 0
...   @property
...   def getter(self):
...       return self._val
...   @getter.setter
...   def setter(self, x):
...       self._val = x
...
>>> x = Prop_imp()
>>> x.setter = 10
>>> x.getter
10

Both of these examples essentially do the same thing in roughly the same amount of code. The advantage of having properties however, is that you may switch from the two whenver you want. Simply add or remove or add the property tags from the getters and setters.

AttributeError

When one tries to access an attribute of the object that does not exist, Python will raise an AttributeError: 'type_of_obj' object has no attribute 'key'.

'Nonetype' has no attribute

This error occurs when the object to the left of the dot notation is None.

>>> class Foo():
...     def bar(self):
...         print(3)
...
>>> a = Foo()
>>> b = a.bar()
3
>>> b.bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'bar'

Naming conventions[2]

  • _single_leading_underscore indicates that the attribute should be only be used internally by the object.
  • __double_leading_and_trailing__underscores__ denote "magic" attributes, built-in attributes in Python that have a particular meaning beyond just holding a key-value pair.

Implementation

In a Python functional implementation of object-oriented programming, attributes can be modeled as a local dictionary within the object frame[3], because attributes are just key-value pairs belonging to the object.

>>> # From Section 2.6.1 of Composing Programs by John DeNero (see citation above)
>>> def make_instance(cls):
        """Return a new object instance, which is a dispatch dictionary."""
        def get_value(name):
            if name in attributes:
                return attributes[name]
            else:
                value = cls['get'](name)
                return bind_method(value, instance)
        def set_value(name, value):
            attributes[name] = value
        attributes = {}
        instance = {'get': get_value, 'set': set_value}
        return instance

References

  1. http://blaag.haard.se/What-s-the-point-of-properties-in-Python/
  2. http://legacy.python.org/dev/peps/pep-0008 PEP 8 Style Guide for Python Code
  3. http://composingprograms.com/pages/26-implementing-classes-and-objects.html#instances Implementation of attributes in Python