Class creation and the relation between properties and methods

I am a beginner and the following class works but if “pythonian” see it I will be shot onsite:

</>
class person:
def init(self,fname,bday,location,email):
self.fname = fname
self.bday = bday
self.location = location
self.email = email

def age(self,date_str):   # 'yyyy-mm-dd'
    import datetime
    from datetime import date
    self.date_str = date_str
    today = date.today()
    bd =  datetime.datetime.strptime(date_str,'%Y-%m-%d').date()
    age = today.year - bd.year - ((today.month, today.day) < (bd.month, bd.day))
    return age

user = person(‘XYZ’,‘1965-12-21’,‘London’, ‘xyz@gmail.com’)
print(user.age(user.bday))
</>

Can someone save my soul by DOING IT right.; please
my questions:

  1. do I include the core modules as shown?
  2. How do I use a property in a method within the class?

Couple of things:

  1. imports should go at the top of the module (file), because
    • The module’s dependencies are then obvious at a glance
    • import costs (a few) cpu cycles. By importing inside a function, you incur that cost repeatedly.
    • By importing inside a function, you may end up in a situation where you are trying to use a module before it’s imported.
    • PEP8 says so.
  2. The correct terminology for user.fname, user.bday, user.age and the like is attribute. You can use attributes within a class via the self variable:
from datetime import datetime
class Person:
    def __init__(self, birthday):
        self.birthday = datetime.fromisoformat(birthday)
    def age(self):
        return (datetime.today() - self.birthday).days // 365

p1 = Person("1988-10-15")
p1.age()

A property is a specific type of attribute, essentially a method masquerading as a non-callable object:

from datetime import datetime
class Person:
    def __init__(self, birthday):
        self.birthday = datetime.fromisoformat(birthday)
    @property
    def age(self):
        return (datetime.today() - self.birthday).days // 365

p1 = Person("1988-10-15")
p1.age

Note that unlike the previous example, the person’s age is accessed without calling the method (p1.age instead of p1.age()). Properties are what is called “syntactic sugar”; a way to make certain common patterns more pleasing to the eye.

WoW…WoW
I have the feeling of achieving a record high jump. This was a great dose that I will nourish for sometime. Thank you Alexander for your wonderful insight.