Iteration: Looping thông qua Data Structures
Như đã biết về Python Basics, List
iteration rất đơn giản. Các developer Python
thường sử dụng looping For
như sau:
bookshelf = [ "The Effective Engineer", "The 4 hours work week", "Zero to One", "Lean Startup", "Hooked" ] for book in bookshelf: print(book)
Vậy là với mỗi quyển trên kệ, (có thể làm mọi thứ) để print nó. Đơn giản & trực quan, đó chính là Python.
Đối với hash data structure, chúng ta cũng có thể sử dụng loop for
nhưng áp dụng key
:
dictionary = { "some_key": "some_value" } for key in dictionary: print("%s --> %s" %(key, dictionary[key])) # some_key --> some_value
Với mỗi key
trong dictionary
, chúng ta sẽ print
key
đó và value
tương ứng của nó.
Cách khác là sử dụng method iteritems
.
dictionary = { "some_key": "some_value" } for key, value in dictionary.items(): print("%s --> %s" %(key, value)) # some_key --> some_value
Chúng ta đã đặt tên 2 biến số là key
& value
, nhưng không cần thiết, có thể đặt bất kì tên nào. Cùng xem:
dictionary_tk = { "name": "Leandro", "nickname": "Tk", "nationality": "Brazilian", "age": 24 } for attribute, value in dictionary_tk.items(): print("My %s is %s" %(attribute, value)) # My name is Leandro # My nickname is Tk # My nationality is Brazilian # My age is 24
Rõ ràng, chúng ta đã sử dụng attribute như 1 tham số cho Dictionary
key
& nó hoạt động rất tốt. Quá tuyệt vời!
Classes & Objects
Một chút lý thuyết
Objects là đại diện cho các đối tượng trong thực tế như xe hơi, chó, xe đạp. Các objects sẽ chia sẻ 2 đặc tính chủ chốt là: data và behavior.
Xe sẽ có data, như số các bánh xe, số cửa sổ và sức chứa chỗ ngồi. Chúng sẽ phơi bày behavior: có thể nâng lên, dừng lại, hiển thị lượng nhiên liệu còn lại…
Chúng ta nhận diện data như các attributes & behavior như các methods trong lập trình hướng đối tượng.
Data → Attributes và Behavior → Methods
Và 1 Class chính là blueprint mà từ đây các objects đơn lẻ sẽ được tạo ra. Trên thực tế, chúng ta thường tìm các objects cùng loại với nhau. Như xe hơi đề có động cơ, bánh xe, cửa… và mỗi xe được build từ cùng bộ blueprints, có cùng các components.
Python Object-Oriented Programming mode: ON
Trong vai trò 1 ngôn ngữ lập trình hướng đối tượng, Python có 3 con concepts: class & object.
Một class là 1 blueprint, 1 model cho các objects của class đó.
Nói chung, 1 class chỉ là 1 model hoặc 1 cách để define attributes và behavior (như đã đề cập trong section theory). Ví dụ, 1 phương tiên di chuyển class có attributes riêng dùng để xác định liệu objects nào là các phương tiện di chuyển. Số lượng các bánh xe, loại bồn chứa, sức chứa chỗ ngồi và vận tốc maximum đều là các attributes của 1 phương tiện di chuyển.
Từ đây, chúng ta có thể xem syntax Python cho các classes:
class Vehicle: pass
Chúng ta define classes với 1 class statement – và chỉ có vậy. Dễ mà, phải không?
Objects là các instances của 1 class. Chúng ta tạo 1 instance bằng cách đặt tên cho class.
car = Vehicle() print(car) # <__main__.Vehicle instance at 0x7fb1de6c2638>
Ở đây, car
là 1 object (hoặc instance) của class Vehicle
.
Lưu ý rằng phương tiện di chuyển class của chúng ta có 4 attributes: số lượng bánh xe, loại bồn chứa, sức chứa chỗ ngồi và vận tốc tối đa. Chúng ta đặt tất cả những attributes này khi tạo 1 phương tiện object. Vậy nên ở đây sẽ define class để nhận data khi khởi tạo nó:
class Vehicle: def __init__(self, number_of_wheels, type_of_tank, seating_capacity, maximum_velocity): self.number_of_wheels = number_of_wheels self.type_of_tank = type_of_tank self.seating_capacity = seating_capacity self.maximum_velocity = maximum_velocity
Chúng ta sử dụng method init
, gọi là 1 constructor method. Vì vậy, khi tạo phương tiện di chuyển object, chúng ta có thể define những attributes này. Hãy tưởng tượng rằng bạn rất yêu thích loại Tesla Model S, và muốn tạo loại object này. Nó sẽ có 4 bánh xe, chạy năng lượng điện, gồm 5 ghế và vận tốc tối đa là 250km/giờ(155 mph). Tạo object như sau:
tesla_model_s = Vehicle(4, 'electric', 5, 250)
Bốn bánh + “loại bồn chứa” bằng điện + 5 ghế + vận tốc tối đa 250km/ giờ
Tất cả các attributes đã được thiết lập. Nhưng làm thế nào để tiếp cận được các giá trị của những attributes này? Chúng ta gửi 1 tin nhắn đến object hỏi về chúng, gọi nó là 1 method, là hành vi của object trên. Hãy implement nó:
class Vehicle: def __init__(self, number_of_wheels, type_of_tank, seating_capacity, maximum_velocity): self.number_of_wheels = number_of_wheels self.type_of_tank = type_of_tank self.seating_capacity = seating_capacity self.maximum_velocity = maximum_velocity def number_of_wheels(self): return self.number_of_wheels def set_number_of_wheels(self, number): self.number_of_wheels = number
Đây là 1 implementation của 2 methods: number_of_wheels và set_number_of_wheels. Chúng ta gọi nó là getter
& setter
. Vì getter
lấy attribute value và setter
thiết lập 1 giá trị mới cho attribute đó.
Trong Python, thì sử dụng @property
(decorators
) để define getters
và setters
.
class Vehicle: def __init__(self, number_of_wheels, type_of_tank, seating_capacity, maximum_velocity): self.number_of_wheels = number_of_wheels self.type_of_tank = type_of_tank self.seating_capacity = seating_capacity self.maximum_velocity = maximum_velocity @property def number_of_wheels(self): return self.number_of_wheels @number_of_wheels.setter def number_of_wheels(self, number): self.number_of_wheels = number
Và sử dụng các methods này như những attributes:
tesla_model_s = Vehicle(4, 'electric', 5, 250) print(tesla_model_s.number_of_wheels) # 4 tesla_model_s.number_of_wheels = 2 # setting number of wheels to 2 print(tesla_model_s.number_of_wheels) # 2
Điều này có khác 1 chút với việc define methods. Các methods hoạt động như là các attributes. Ví dụ, khi set số bánh xe mới, chúng ta không áp số 2 vào thành 1 tham số mà set giá trị 2 vào number_of_wheels
. Đây là 1 cách để viết code pythonic
getter
và setter
.
Nhưng có thể sử dụng methods cho những thứ khác, như method “make_noise”
class Vehicle: def __init__(self, number_of_wheels, type_of_tank, seating_capacity, maximum_velocity): self.number_of_wheels = number_of_wheels self.type_of_tank = type_of_tank self.seating_capacity = seating_capacity self.maximum_velocity = maximum_velocity def make_noise(self): print('VRUUUUUUUM')
Khi call method này, nó chỉ trả lại 1 string “VRRRRUUUUM.”
tesla_model_s = Vehicle(4, 'electric', 5, 250) tesla_model_s.make_noise() # VRUUUUUUUM
Encapsulation: Ẩn thông tin
Encapsulation là cơ chế giới hạn khả năng tiếp cận trực tiếp đến data & methods của các objects. Nhưng cùng lúc đó, nó lại hỗ trỡ việc vận hành trên data đó (methods của các objects)
“Encapsulation được dùng để ẩn Data Members & Members function. VỚi Định nghĩa này, encapsulation đồng nghĩa là việc hiển thị nội bộ của 1 object được ẩn toàn bộ khỏi tầm nhìn của definition Đến từ Object đó” — Wikipedia
Tất cả hiển thị nội bộ của 1 object được ẩn khỏi bên ngoài. Chỉ có object đó mới tương tác được với data nội bộ của nó.
Đầu tiên, chúng ta cần phải hiểu cách hoạt động của các biến số instance public
và non-public
và methods.
Các biến số Instance công khai
Đối với 1 Python class, khởi tạo 1 public instance variable
trong constructor method của chúng ta.
Trong method constructor:
class Person: def __init__(self, first_name): self.first_name = first_name
Ở đây, áp dụng value first_name
như 1 argument đến public instance variable
.
tk = Person('TK') print(tk.first_name) # => TK
Trong class:
class Person: first_name = 'TK'
Không cần áp dụng first_name
như 1 argument, và tất cả các instance objects sẽ có 1 class attribute
được khởi tạo với TK
.
tk = Person() print(tk.first_name) # => TK
Tốt. Hiện chúng ta đã biết sử dụng public instance variables
và class attributes
. Điều thú vị khác nữa về phần public
là có thể quản lý giá trị của biến, nghĩa là object
có thể quản lý giá trị biến số của nó: các giá trị biến số Get
và Set
.
Nhắc đến Person
, nếu muốn set giá trị khác cho biến first_name
:
tk = Person('TK') tk.first_name = 'Kaio' print(tk.first_name) # => Kaio
Đấy, chúng ta chỉ set giá trị khác (kaio
) cho biến instance first_name
và nó đã cập nhật giá trị. Đơn giản vậy thôi. Vì là biến public
nên sẽ làm được điều đó.
Biến Instance không công khai
“Ở đây, chúng ta không sử dụng thuật ngữ “private” vì không có attribute nào thực sự riêng tư trong Python (mà không có 1 lượng lớn công việc không cần thiết)” — PEP 8
Giống như public instance variable
, chúng ta có thể define non-public instance variable
trong method constructor hoặc trong class. Điểm khác biệt syntax chính là: đối với non-public instance variables
, sẽ sử dụng gạch dưới (_
) trước tên variable
.
“‘Các biến instance private mà không thể tiếp cận ngoài trừ lúc ở trong 1 object thì sẽ không tồn tại trong python. Tuy nhiên, có 1 quy ước được hầu hết code python theo là: 1 name prexide với 1 dấu gạch dưới (như: _spam
) nên được xem như 1 phần không công khai của API (dù nó là 1 function, 1 method hay 1 data member)” — Python Software Foundation
Ví dụ:
class Person: def __init__(self, first_name, email): self.first_name = first_name self._email = email
Bạn có thấy biến email
không? Đây là cách chúng ta define 1 non-public variable
tk = Person('TK', 'tk@mail.com') print(tk._email) # tk@mail.com
“Chúng ta có thể access & cập nhật nó. Non-public variables
chỉ là 1 Quy ước và nên được xem như phần non-public của API”
Vì vậy, sử dụng 1 method cho phép define trong class definition. Cùng implement 2 methods (email
và update_email
) để hiểu rõ hơn:
class Person: def __init__(self, first_name, email): self.first_name = first_name self._email = email def update_email(self, new_email): self._email = new_email def email(self): return self._email
Bây giờ chúng ta có thể update & access non-public variables
bằng những methods đó. Cùng xem:
tk = Person('TK', 'tk@mail.com') print(tk.email()) # => tk@mail.com tk._email = 'new_tk@mail.com' print(tk.email()) # => tk@mail.com tk.update_email('new_tk@mail.com') print(tk.email()) # => new_tk@mail.com
- Khởi tạo 1 object mới bằng
first_name
TK vàemail
tk@mail.com - Printt email bằng cách tiếp cận
non-public variable
với 1 method - Cố gắng set
email
mới ngoài class - Cần phải xem
non-public variable
như phầnnon-public
của API - Cập nhật
non-public variable
bằng method instance - Thành công! Chúng ta có thể cập nhật nó trong class bằng method helper
Public Method
Với public methods
, chúng ta cũng có thể sử dụng ngoài class:
class Person: def __init__(self, first_name, age): self.first_name = first_name self._age = age def show_age(self): return self._age
Thử test xem:
tk = Person('TK', 25) print(tk.show_age()) # => 25
Tốt, vậy là không có vấn đề gì.
Non-public Method
Nhưng với non-public methods
thì không làm được điều này. Hãy implement cùng class Person
nhưng bây giờ với 1 show_age
non-public method
bằng 1 dấu gạch dưới (_
).
class Person: def __init__(self, first_name, age): self.first_name = first_name self._age = age def _show_age(self): return self._age
Giờ chúng ta sẽ cố gọi non-public method
này với object của mình:
tk = Person('TK', 25) print(tk._show_age()) # => 25
“Chúng ta có thể access & Update nó. Non-public methods
chỉ là 1 quy ước & nên được xem như 1 phần non-public của API”
Dưới đây là ví dụ về cách sử dụng non-public methods:
class Person: def __init__(self, first_name, age): self.first_name = first_name self._age = age def show_age(self): return self._get_age() def _get_age(self): return self._age tk = Person('TK', 25) print(tk.show_age()) # => 25
Chúng ta có 1 _get_age
non-public method
và 1 show_age
public method
. Object của chúng ta có thể sử dụng show_age
(bên ngoài class) và _get_age
chỉ được sử dụng bên trong class definition (trong method show_age
). Nhưng 1 lần nữa, đây chỉ là vấn đề liên quan đến quy ước.
Encapsulation Summary
Với encapsulation, có thể đảm bảo rằng hiển thị nội bộ của object được ẩn.
Inheritance: các hành vi và các đặc tính
Một vài objects nào đó sẽ sở hữu vài điểm chung: behavior & characterists của chúng.
Trong lập trình hướng đối tượng, các class có thể thừa hưởng những đặc tính (data) và hành vi (methods) tương tự từ class khác.
Cùng xem 1 ví dụ khác và implement nó bằng Python.
Hãy tưởng tượng 1 chiếc xe hơi. Số lượng bánh xe, sức chứa chỗ ngồi và vận tốc tối đa là tất cả các attributes của 1 chiếc xe. Có thể nói rằng 1 class ElectricCar thừa hưởng cùng các attributes từ class Car thông dụng.
Class Car đã implement như sau:
class Car: def __init__(self, number_of_wheels, seating_capacity, maximum_velocity): self.number_of_wheels = number_of_wheels self.seating_capacity = seating_capacity self.maximum_velocity = maximum_velocity
Một khi đã khởi tạo, chúng ta có thể sử dụng tất cả instance variables
đã được tạo ra. Tốt.
Trong Python, hãy áp dụng parent class
vào child class
như 1 tham số. Một class ElectricCar có thể kế thừa từ class Car.
class ElectricCar(Car): def __init__(self, number_of_wheels, seating_capacity, maximum_velocity): Car.__init__(self, number_of_wheels, seating_capacity, maximum_velocity)
Đơn giản vậy thôi, chúng ta không cần phải implement bất kì method nào khác, vì class nà đã có rồi (được thừa hưởng từ class Car).
my_electric_car = ElectricCar(4, 5, 250) print(my_electric_car.number_of_wheels) # => 4 print(my_electric_car.seating_capacity) # => 5 print(my_electric_car.maximum_velocity) # => 250
Thật đẹp, đúng không?
Tổng quan
Như vậy, bài viết này đã giúp chúng ta nắm được những kiến thức Python cơ bản:
- Cách hoạt động của các biến Python
- Cách hoạt động của conditional statements Python
- Cách looping Python (while & for) hoạt động
- Cách sử dụng Lists: Collection | Array
- Dictionary Key-Value Collection
- Cách lặp thông qua data structures
- Objects & Classes
- Các attibutes như data của objects
- Methods như hành vi của các objects
- Sử dụng getters và setters của Python & property decorator
- Encapsulation: ẩn thông tin
- Inheritance: behaviors (hành vi) và characteristics (đặc tính)
Bạn có thể đọc thêm quá trình nghiên cứu lập trình của tôi ở The Renaissance Developer.
Chúc vui, đừng quên hãy tiếp tục học hỏi và luôn cố gắng coding nhé!
Xem thêm các vị trí python tuyển dụng từ công ty lớn
Nguồn: TopDev via medium.freecodecamp.com