
# Common decordator 1:  @property

# Tagging a method with @property makes it possible to access 
# an object’s method like a regular attribute.
#
# A property decorator is actually a getter method.

# Example:

# Say you have a Mass class that stores the mass in kilos and pounds:

class Mass:
    def __init__(self, kilos):
        self.kilos = kilos
        self.pounds = kilos * 2.205

# Usage:

mass = Mass(100)

print(mass.kilos)
print(mass.pounds)

# It is stupid to store 2 variables. One variable is enough.
# Better class definition:

class Mass:
    def __init__(self, kilos):
        self.kilos = kilos
            
    def pounds(self):
        return self.kilos * 2.205

# But NOW, you have to use this to get the data:

mass = Mass(100)

print(mass.kilos)
print(mass.pounds())		# NOT UNIFORM !!!

# This is where a @property decorator helps you.
#
# If you mark the pounds() method with @property, Python allows 
# you to **call mass.pounds** without parentheses again.

class Mass:
    def __init__(self, kilos):
        self.kilos = kilos
        
    @property			# This is a DECORATOR (getter) function
    def pounds(self):
        return self.kilos * 2.205

# NOW, you have to use the pound "variable name" and
# Python will call the PARAMETER-LESS function pound()

mass = Mass(100)

print(mass.kilos)
print(mass.pounds)            	# UNIFORM again !!!



