16.6. OOP Attribute About

  • Attributes are also known as "Properties" or "Fields"

  • Attributes store information for instances

  • Access field values using dot (.) notation

field

Variable inside the class. Can be used as a synonym of property or attribute.

property

Variable inside the class. Can be used as a synonym of field or attribute.

state

Current values of all variables in a class. Changes during lifetime of an object. Represents current state of an object.

attribute

Variable inside the class. Can be used as a synonym of field or property. In Python, methods also can be described as attributes, but justification for that is a bit more complex which will be introduced later in a book.

namespace

Container for storing related data

16.6.1. About

An example "Glass with Water" can illustrate the distinction of properties and state attributes:

Properties:

  • color

  • width

  • height

  • radius

  • capacity

  • net mass (without water)

Fields:

  • volume (how much water is currently in the glass)

  • gross mass = net mass + water mass (water mass depends on its volume used))

../../_images/oop-classes-glass.jpg

Figure 16.3. Source: [1]

Class example with distinction of properties and field attributes.

>>> class Glass:
...
...     # Properties
...     color: str
...     width: float
...     height: float
...     radius: float
...     capacity: float
...     net_mass: float  # without water
...
...     # Fields
...     volume: float  # how much water is currently in the glass
...     gross_mass: float  # mass depends on its volume used (glass+water)

16.6.2. What are attributes?

  • Scalars creates values

  • Identifiers and values creates variables

  • Values with relations creates structures

  • Structures with identifiers creates data

  • Data with context and relations creates information

Scalars creates values:

>>> 'Mark'  
>>> 'Watney'  
>>> '1969-07-21'  

Identifiers and values creates variables:

>>> firstname = 'Mark'
>>> lastname = 'Watney'
>>> birthdate = '1969-07-21'

Related values creates structures:

>>> user = ['Mark', 'Watney', '1969-07-21']

Structures with identifiers creates data:

>>> user = {
...     'firstname': 'Mark',
...     'lastname': 'Watney',
...     'birthdate': '1969-07-21',
... }

Data with context creates classes:

>>> class User:
...     firstname: str
...     lastname: str
...     birthdate: str
>>>
>>> user = User()
>>> user.firstname = 'Mark'
>>> user.lastname = 'Watney'
>>> user.birthdate = '1969-07-21'

Classes with relations creates information:

>>> class Date:
...     year: int
...     month: int
...     day: int
>>>
>>> class User:
...     firstname: str
...     lastname: str
...     birthdate: Date
>>>
>>>
>>> birthdate = Date()
>>> birthdate.year = 1969
>>> birthdate.month = 7
>>> birthdate.day = 21
>>>
>>> user = User()
>>> user.firstname = 'Mark'
>>> user.lastname = 'Watney'
>>> user.birthdate = birthdate

16.6.3. State

>>> class User:
...     firstname: str
...     lastname: str
...     birthdate: str
>>> user = User()
>>> vars(user)
{}
>>> user.firstname = 'Mark'
>>> user.lastname = 'Watney'
>>> user.birthdate = '1969-07-21'
>>> vars(user)
{'firstname': 'Mark', 'lastname': 'Watney', 'birthdate': '1969-07-21'}
>>> user.firstname = 'Melissa'
>>> user.lastname = 'Lewis'
>>> user.birthdate = '1961-04-12'
>>> vars(user)
{'firstname': 'Melissa', 'lastname': 'Lewis', 'birthdate': '1961-04-12'}

16.6.4. Namespace

  • Class creates space, in which names has meaning

Unrelated variables:

>>> firstname: str
>>> lastname: str

Related variables:

>>> user_firstname: str
>>> user_lastname: str

Class creates common space for names (namespace):

>>> class User:
...     firstname: str
...     lastname: str

16.6.5. References

>>> mark = User()
>>> mark.firstname = 'Mark'
>>> mark.lastname = 'Watney'
>>>
>>> vars(mark)
{'firstname': 'Mark', 'lastname': 'Watney'}
>>>
>>>
>>> melissa = User()
>>> melissa.firstname = 'Melissa'
>>> melissa.lastname = 'Lewis'
>>>
>>> vars(melissa)
{'firstname': 'Melissa', 'lastname': 'Lewis'}
>>> class User:
...     firstname: str
...     lastname: str
...     age: int
...
>>>
>>> mark = User()
>>> mark.firstname
Traceback (most recent call last):
AttributeError: 'User' object has no attribute 'firstname'
>>> mark.firstname = 'Mark'
>>> mark.lastname = 'Watney'
>>> mark.email = 'mwatney@nasa.gov'

16.6.6. Assignments

"""
* Assignment: OOP Field Define
* Type: class assignment
* Complexity: easy
* Lines of code: 2 lines
* Time: 2 min

English:
    1. Modify instance `mark`
    2. Add field `firstname` with value 'Mark'
    3. Add field `lastname` with value 'Watney'
    4. Run doctests - all must succeed

Polish:
    1. Zmodyfikuj instancję `mark`
    2. Dodaj pole `firstname` o wartości 'Mark'
    3. Dodaj pole `lastname` o wartości 'Watney'
    4. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from pprint import pprint
    >>> from inspect import isclass

    >>> assert isclass(User)
    >>> assert isinstance(mark, User)
    >>> assert hasattr(mark, 'firstname')
    >>> assert hasattr(mark, 'lastname')
    >>> assert getattr(mark, 'firstname') == 'Mark'
    >>> assert getattr(mark, 'lastname') == 'Watney'
"""

class User:
    pass

mark = User()

# Modify instance `mark`
# Add field `firstname` with value 'Mark'
# type: str
...

# Modify instance `mark`
# Add field `lastname` with value 'Watney'
# type: str
...

"""
* Assignment: OOP Field Define
* Type: class assignment
* Complexity: easy
* Lines of code: 1 lines
* Time: 2 min

English:
    1. Modify instance `mark`
    2. Add field `is_authenticated` with value False
    3. Run doctests - all must succeed

Polish:
    1. Zmodyfikuj instancję `mark`
    2. Dodaj pole `is_authenticated` o wartości False
    3. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from pprint import pprint
    >>> from inspect import isclass

    >>> assert isclass(User)
    >>> assert isinstance(mark, User)
    >>> assert hasattr(mark, 'is_authenticated')
    >>> assert getattr(mark, 'is_authenticated') is False
"""

class User:
    pass

mark = User()

# Modify instance `mark`
# Add field `is_authenticated` with value False
# type: bool
...


"""
* Assignment: OOP Field Vars
* Type: class assignment
* Complexity: easy
* Lines of code: 1 lines
* Time: 2 min

English:
    1. Use instance `mark`
    2. Define `result: dict` with current state of `mark` object
       (all attributes and values in dict format)
    3. Run doctests - all must succeed

Polish:
    1. Użyj instancji `mark`
    2. Zdefiniuj `result: dict` z aktualnym stanem obiektu `mark`
       (wszystkie atrybuty i wartości w formacie dict)
    3. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from pprint import pprint
    >>> from inspect import isclass

    >>> assert isclass(User)
    >>> assert isinstance(mark, User)
    >>> assert hasattr(mark, 'firstname')
    >>> assert hasattr(mark, 'lastname')
    >>> assert hasattr(mark, 'is_authenticated')
    >>> assert getattr(mark, 'firstname') == 'Mark'
    >>> assert getattr(mark, 'lastname') == 'Watney'
    >>> assert getattr(mark, 'is_authenticated') is False
"""

class User:
    pass

mark = User()
mark.firstname = 'Mark'
mark.lastname = 'Watney'
mark.is_authenticated = False


# Define `result: dict` with current state of `mark` object
# (all attributes and values in dict format)
# type: dict[str, str|bool]
result = ...