Python OOP – Lập trình hướng đối tượng với Python

21/02/2023 - lượt xem
Chia sẻ
 
Rate this post

Trong python, Lập trình hướng đối tượng (OOP) là một mô hình lập trình sử dụng các đối tượng, các class trong quá trình lập trình. Mục đích của viêc này là để triển khai giả lập lại các đối tượng trong thực tế thông qua cơ chế kế thừa, đa hình, đóng gói…

Tư tưởng chính của lập trình hướng đối tượng là liên kết các chức năng và chức năng trên dữ liệu đó thành một đơn vị duy nhất để các thành phần khác của mã nguồn không thể truy cập dữ liệu này.

Ý tưởng chính của lập trình hướng đối tượng (OOPs)

Ý tưởng chính của lập trình Hướng đối tượng trong Python
Ý tưởng chính của lập trình Hướng đối tượng trong Python

Class – lớp trong Python

Một lớp là tập hợp của đối tượng. Một lớp chứa định danh hoặc khung mẫu để tạo ra các đối tượng. Nó là 1 thực thể logics chứa các thuộc tính và phương thức.

Để hiểu điều này chúng ta xem xét ví dụ sau, giả sử chúng ta cần theo dõi số lượng chó có thể có các thuộc tính khác nhau như giống chó, tuổi. Nếu 1 list được sử dụng, phần tử đầu tiên có thể là giống chó, phần thử thứ 2 là tuổi chó.

Tuy vậy, giả sử có 100 con chó khác nhau, làm sao chúng ta có thể biết phần nào với phần tử nào. Thêm vào đó, sẽ rất phức tạp nếu muốn thêm các thuộc tính khác vào những con chó này. Vấn đề của điều này là sự tổ chức, đó chính là vấn đề mà Class giải quyết.

Một vài điểm chú ý về Python class

  • Các class được tạo bởi từ khóa class
  • Thuốc tính là các biến được gắn liền với class
  • Thuộc tính luôn luôn là public có thể truy cập thông qua dấu chấm  – toán tử truy xuất thông tin “.”, ví dụ MyClass.MyAttribute

Định nghĩa 1 class

class ClassName:
   # Statement-1
   .
   .
   .
   # Statement-N

Ví dụ tạo 1 class trống trong Python

# Python3 program to
# demonstrate defining
# a class

class Dog:
	pass

Trong ví dụ trên, chúng ta tạo 1 class tên Dog và sử dụng từ khóa pass. Chú ý rằng dùng từ khóa pass thì mới khởi tạo 1 class Empty (trống) được.

Đối tượng – Objects trong Python

Một đối tượng là 1 thực thẻ có trạng thái và các hành vi liên quan tới nó. Nó giống như bất kì một đối tượng thế giới thực nào như là chuột, bàn phím, bàn, ghế, bút… Hay trong lập trình thì số 12 cũng là 1 object, chuỗi “Hello, world” cũng là 1 chuỗi.

Một đối tượng bao gồm:

  • State – Trạng thái: nó đại diện bởi ác thuộc tính của 1 đối tượng. Nó cũng phản ảnh các thuộc tính của một đối tượng.
  • Behavior – Hành vi: được đại diện bởi các phương thức của đối tượng.
  • Identify – Định danh: Nó cung cấp 1 tên duy nhất với 1 đối tượng và cho phép một đối tượng tương tác với các đối tượng khác.

Để hiểu về trạng thái, hành vi và định danh, chúng ta cùng xem xét ví dụ về class Dog

  • Định danh có thể được hiểu là tên của con chó
  • Trạng thái, hay các thuộc tính có thể hiểu như là giống chó, màu sắc của con chó.
  • Hành vi có thể được hiểu là các hành động của con chó: ăn, uống, ngủ.

Ví du khởi tạo một đối tượng

obj = Dog()

Từ khóa self trong Python

  • Phương thức trong class phải có một tham số mặc định trong lúc định nghĩa các phương thức. Giá trị cho tham số này không cần phải chỉ định mà Python sẽ tự động cung cấp giá trị khi chạy.
  • nếu chúng ta có 1 phương thức mà không có tham số nào, thì khi đó chugns ta vẫn cần phải có 1 tham số (self)
  • Điều này tương tự với con trỏ trong C++ hay tham chiếu trong Java

Khi chúng ta gọi phương thức này myobject.method(arg1, arg2) sẽ tự động được chuyển đổi bởi Python thành MyClass.method(myobject, arg1, arg2).

self được đại diện cho thể hiện (instance) của class. Bằng cách sử dụng self, chúng ta có thể truy cập thuộc tính và phương thức của class.

Xem thêm ví dụ sau để hiểu hơn về self

#it is clearly seen that self and obj is referring to the same object

class check:
	def __init__(self):
		print("Address of self = ",id(self))

obj = check()
print("Address of class object = ",id(obj))

# this code is Contributed by Samyak Jain

kết quả nhận được là

Address of self =  140124194801032
Address of class object =  140124194801032

Thêm 1 ví dụ nữa về self

# Write Python3 code here

class car():
	
	# init method or constructor
	def __init__(self, model, color):
		self.model = model
		self.color = color
		
	def show(self):
		print("Model is", self.model )
		print("color is", self.color )
		
# both objects have different self which
# contain their attributes
audi = car("audi a4", "blue")
ferrari = car("ferrari 488", "green")

audi.show()	 # same output as car.show(audi)
ferrari.show() # same output as car.show(ferrari)

#note:we can also do like this
print("Model for audi is ",audi.model)
print("Colour for ferrari is ",ferrari.color)
#this happens because after assigning in the constructor the attributes are linked to that particular object
#here attributes(model,colour) are linked to objects(audi,ferrari) as we initialize them
# Behind the scene, in every instance method
# call, python sends the instances also with
# that method call like car.show(audi)

Kết quả nhận được

Model is audi a4
color is blue
Model is ferrari 488
color is green

Chú ý: Từ khóa self là không bắt buộc, bạn có thể đặt bất kì tên gì bạn muốn, tuy nhiên việc đặt là self (theo chuẩn) để giúp cho đọc code cũng như chia sẻ mã nguồn dễ dàng hơn.

Tham khảo thêm về hàm tĩnh trong Python.

Phương thức __init__

Phương thức __init__ trong Python tương tự hàm khởi tạo trong C++ hay Java. Nó được khởi chạy khi 1 đối tượng của 1 class được khởi tạo.

Xem xét 1 số ví dụ về __init__

class Dog:

	# class attribute
	attr1 = "mammal"

	# Instance attribute
	def __init__(self, name):
		self.name = name

# Driver code
# Object instantiation
Rodger = Dog("Rodger")
Tommy = Dog("Tommy")

# Accessing class attributes
print("Rodger is a {}".format(Rodger.__class__.attr1))
print("Tommy is also a {}".format(Tommy.__class__.attr1))

# Accessing instance attributes
print("My name is {}".format(Rodger.name))
print("My name is {}".format(Tommy.name))

Kết quả in màn hình

Rodger is a mammal
Tommy is also a mammal
My name is Rodger
My name is Tommy

Kế thừa – inheritance

Kế thừa là khả năng của 1 lớp kế thừa các thuộc tính từ 1 lớp khác. Lớp kế thừa được gọi là lớp dẫn xuất hoặc lớp con, lớp này sẽ dẫn xuất các thuộc tính từ lớp cha – lớp cơ sở.

Đọc thêm bài kiến thức mở rộng về kế thừa trong lập trình OOP Python.

Lợi ích của kế thừa bao gồm

  • Nó thể hiện mối quan hệ thế giới thực
  • Cung cấp khả năng tái sử dụng code. Chúng ta không cần phải viết code lặp lại nhiều lần. Đồng thời cho phép thêm tính năng mới vào class mà không cần phải chỉnh sửa
  • Nó có tính chất bắc cầu, nghĩa là nếu class kế thừa class A, thì tất cả các lớp con của lớp B sẽ tự động kế thừa A

Đơn kế thừa – single inheritance

Đơn kế thừa cho phép lớp dẫn xuất chỉ kế thừa từ 1 lớp cha

Kế thừa đa tầng – Multilevel inheritance

Kế thừa đa tầng cho phép lớp dẫn xuất kế thừa các thuộc tính từ lớp cha ngay lập tức, lớp này có thể kế thừa tiếp các thuộc tính từ cha của nó tiếp.

Kế thừa phân cấp – Hierarchical inheritance

Kế thừa mức phân cấp cho phép từ 1 lớp cha có thể có nhiều lớp dẫn xuất

Đa kế thừa – Multiple Inheritance:

Đa kế thừa cho phép 1 lớp dẫn xuất có thề kế thừa từ nhiều lớp cha

# Python code to demonstrate how parent constructors
# are called.

# parent class
class Person(object):

	# __init__ is known as the constructor
	def __init__(self, name, idnumber):
		self.name = name
		self.idnumber = idnumber

	def display(self):
		print(self.name)
		print(self.idnumber)
		
	def details(self):
		print("My name is {}".format(self.name))
		print("IdNumber: {}".format(self.idnumber))
	
# child class
class Employee(Person):
	def __init__(self, name, idnumber, salary, post):
		self.salary = salary
		self.post = post

		# invoking the __init__ of the parent class
		Person.__init__(self, name, idnumber)
		
	def details(self):
		print("My name is {}".format(self.name))
		print("IdNumber: {}".format(self.idnumber))
		print("Post: {}".format(self.post))


# creation of an object variable or an instance
a = Employee('Rahul', 886012, 200000, "Intern")

# calling a function of the class Person using
# its instance
a.display()
a.details()

Kết quả

Rahul
886012
My name is Rahul
IdNumber: 886012
Post: Intern

Trong ví dụ trên chúng ta tạo 2 class Person (class cha) và Employee (class con). Class Employee kế thừ từ class Person. Chúng ta có thể sử dụng các phương thức của person thông qua employee.

Tính đa hình – Polymorphism

Tính đa hình đơn giản nghĩa là có nhiều hình thức khác nhau. Ví dụ, chúng ta cần xác định xem loài chim đã cho có bay được hay không, bằng cách sử dụng tính đa hình, chúng ta có thể thực hiện việc này bằng 1 hàm duy nhất.

class Bird:

	def intro(self):
		print("There are many types of birds.")

	def flight(self):
		print("Most of the birds can fly but some cannot.")

class sparrow(Bird):

	def flight(self):
		print("Sparrows can fly.")

class ostrich(Bird):

	def flight(self):
		print("Ostriches cannot fly.")

obj_bird = Bird()
obj_spr = sparrow()
obj_ost = ostrich()

obj_bird.intro()
obj_bird.flight()

obj_spr.intro()
obj_spr.flight()

obj_ost.intro()
obj_ost.flight()

Kết quả

There are many types of birds.
Most of the birds can fly but some cannot.
There are many types of birds.
Sparrows can fly.
There are many types of birds.
Ostriches cannot fly.

Tính đóng gói – Encapsulation

Tính đóng gói là 1 trong các khái niệm cơ bản của lập trình hướng đối tượng. Nó mô tả về việc đóng gói dữ liệu và các phương thức trong 1 đơn vị.

Việc này đặt ra các hạn chết đối với việc truy cập trực tiếp với biến, phương thức, từ đó hạn chế các sử đổi dữ liệu vô ý.

Biến của các đối tượng chỉ có thể thay đổi bằng phương thức của đôi tượng, các biến này là biến private.

# Python program to
# demonstrate private members

# Creating a Base class
class Base:
	def __init__(self):
		self.a = "GeeksforGeeks"
		self.__c = "GeeksforGeeks"

# Creating a derived class
class Derived(Base):
	def __init__(self):

		# Calling constructor of
		# Base class
		Base.__init__(self)
		print("Calling private member of base class: ")
		print(self.__c)


# Driver code
obj1 = Base()
print(obj1.a)

# Uncommenting print(obj1.c) will
# raise an AttributeError

# Uncommenting obj2 = Derived() will
# also raise an AtrributeError as
# private member of base class
# is called inside derived class

Biến __c là biến dạng private, biến private được xác định theo cách đặt tên biến.

Tham khảo thêm về getter và setter trong python.

Trừu tượng hóa dữ liệu

Với OOP thì nó sẽ ẩn toàn bộ các thông tin code không cần thiết đối với người dùng. Khi chúng ta không muốn đưa ra các phần nhạy cảm trong quá trình triển khai code thì đó là lúc cần dùng trừu tượng hóa. Trong Python chính là việc tạo các abstract class.

 

Tổng kết

Trong bài viết này CodeTuTam đã cùng các bạn đi tìm hiểu về những khái niệm trong lập trình hướng đối tượng với Python. Về cơ bản, kiến thức OOP trong các ngôn ngữ lập trình khác nhau cũng sẽ có độ giống nhau nhất định. Nên nếu các bạn đã có kinh nghiệm, CodeTuTam tin rằng rất nhanh chóng các bạn sẽ làm quen với OOP trong Python.

Bài viết về lập trình hướng đối tượng trong Python là nội dung bổ trợ thêm cho lập trình Odoo. Hi vọng bài viết này giúp ích cho các bạn trong quá trình học tập và làm việc cùng Python.

 

 

    Liên hệ với chúng tôi

    Để lại thông tin để nhận được các bài viết khác

    Rate this post

    Xem thêm nhiều bài tin mới nhất về Odoo

    Xem thêm