Created for
The minimal class definition in Python looks like:
class ClassName:
pass
class Person:
pass
In python, it's simple:
object_name = ClassName()
# create objects of class Person:
pesho = Person()
maria = Person()
# let's check:
print( type(pesho) )
print( type(maria) )
# <class '__main__.Person'>
# <class '__main__.Person'>
Objects created from the same class
have same type
, but they are different entities:
class Person:
pass
maria = Person()
pesho = Person()
print( maria == pesho)
#False
# write in object attribute:
object_name.attribute = "value of any type"
# read from attribute:
var = object_name.attribute
maria = Person()
# write in object attribute:
maria.name = "Maria"
print(maria.name)
# read from attribute:
mn = maria.name
print(mn)
As we'll see later, this is not the proper way to create object's attributes in Python. This is an example of dot notation, used to access object's attributes
__dict__
, which store an object's (writeable) attributes
class Person:
pass
maria = Person()
# set attribute:
maria.name = "Maria"
maria.age = 100
print(maria.__dict__)
# {'name': 'Maria', 'age': 100}
class Person:
name = "Anonymous"
age = 100
maria = Person()
pesho = Person()
print(maria.name, maria.age)
print(pesho.name, pesho.age)
# Anonymous 100
# Anonymous 100
A method is a function that "belongs to" an object.
class ClassName:
def method_name(self):
pass
self
class Person:
def greet(self):
print("Hi there! I'm", self.name)
# create some objects of class Person:
maria = Person()
maria.name = "Maria Popova"
pesho = Person()
pesho.name = "Pesho"
# call greet() method on maria. Python will send the maria object reference to the self parameter.
maria.greet()
# call greet() method on pesho
pesho.greet()
# OUTPUT:
# Hi there! I'm Maria Popova
# Hi there! I'm Pesho
When a method is invoked from an object, Python automatically passes the object reference to the first parameter in the method definition.
class TestSelf:
def test(self, obj):
print(self == obj)
obj1 = TestSelf()
# lets check if obj1 == self
obj1.test( obj1 )
# True
__init__()
method__init__()
method__init__()
class ClassName:
def __init__(self):
pass
# class definition
class ClassA:
def __init__(self):
print("An object of ClassA is created!")
# objects creation:
obj1 = ClassA()
obj2 = ClassA()
# output:
# An object of ClassA is created!
# An object of ClassA is created!
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
print("Hi there! I'm {}, {} years old!".
format(self.name, self.age))
maria = Person("Maria Popova", 25)
pesho = Person("Pesho", 27)
maria.greet()
pesho.greet()
# Hi there! I'm Maria Popova, 25 years old!
# Hi there! I'm Pesho, 27 years old!
__init__()
methods in Python, there are many other predefined special methods, also called magic methods, which have the same notation form:
__magic__()
The double underscore is often called dunder, thus the methods - dunder methods
__str__()
method which will be used, when you call the str(), format() or print() functions of a class instance
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return "name = {}\nage = {}\n".format(self.name, self.age)
maria = Person("Maria Popova", 25)
print(maria)
# name = Maria Popova
# age = 25
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return """# This is representation of an object:
obj = Person()
obj.name = {}
obj.age = {}""".format(self.name, self.age)
maria = Person("Maria Popova", 25)
print(maria)
Note, that the __repr__ method will be invoked, when print(maria)
is executed!
__str__
vs __repr__
class BankAccount():
pass
maria_account = BankAccount("Maria", 1_300)
pesho_account = BankAccount("Pesho", 100)
print(maria_account)
print(maria_account)
# OUTPUT:
#BankAccount:
# owner = Maria
# balance = 1300
#BankAccount:
# owner = Pesho
# balance = 100
Naming | Type | Meaning |
---|---|---|
name | Public | Attributes, that can be freely used inside or outside of a class definition. |
_name | Protected | Protected attributes should not be used outside of the class definition, unless inside of a subclass definition. |
__name | Private | This kind of attribute should be inaccessible and invisible. It's neither possible to read nor write to those attributes, except inside of the class definition itself. |
Python did not provide a truly private attributes!
The dunder attributes are just prefixed with the _ClassName
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age
def __str__(self):
return "name = {}; __age = {}".format(self.name, self.__age)
maria = Person("Maria Popova", 25)
# let's try to change Maria's age:
maria.__age = 100
print("maria.__age is set to ", maria.__age)
print(maria)
# but __age is not hidden! Look:
maria._Person__age = 100
print("maria.__age is set to ", maria.__age)
print(maria)
__dict__ - revealing object's dictionary
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age
maria = Person("Maria Popova", 25)
# inspect object attributes dictionary:
print( maria.__dict__ )
# inspect class attributes dictionary:
print( Person.__dict__ )
dir()
- revealing all object's attributesdir()
used with an object name as argument will reveal most of the attributes defined for that object. Check dir() on python3 docs for more information.
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age
maria = Person("Maria Popova", 25)
print("maria has next attributes:")
print( dir(maria) )
# of course, dir() is calling the __dir__() method on the object, but it's better to use the function call, though you can do that:
print( maria.__dir__() )