Tuples

Tuple là một kiểu dữ liệu trong Python tương tự như list, nhưng có tính bất biến (immutable), tức là không thể thay đổi sau khi khai báo.

1️⃣ Khai báo Tuple

Cách khai báo một tuple:

# Tuple có nhiều phần tử
t1 = (1, 2, 3)
t2 = ("apple", "banana", "cherry")
# Tuple có một phần tử (phải có dấu phẩy `,`)
t3 = (5,)
t4 = ("hello",)
# Tuple rỗng
t5 = ()

Lưu ý: Nếu không có dấu phẩy ,, Python sẽ hiểu đây là kiểu dữ liệu khác (không phải tuple):

t = (5)  # Đây là số nguyên, không phải tuple!
print(type(t))  # Output: <class 'int'>

2️⃣ Truy cập phần tử trong Tuple

Giống list, có thể dùng chỉ mục (index):

t = (10, 20, 30, 40)
print(t[0])  # Output: 10
print(t[2])  # Output: 30
print(t[-1]) # Output: 40 (Truy cập từ cuố

Slicing (Cắt chuỗi)

print(t[1:3])  # Output: (20, 30)
print(t[:2])   # Output: (10, 20)
print(t[::2])  # Output: (10, 30) (Lấy cách 2 phần tử)

3️⃣ Tuple là bất biến (Immutable)

t = (1, 2, 3)
t[0] = 10  # ❌ Lỗi! Tuple không thể thay đổi

Cách “thay đổi” Tuple (gián tiếp)
Có thể chuyển tuple thành list, thay đổi, rồi chuyển lại tuple:

t = (1, 2, 3)
t_list = list(t)  # Chuyển tuple thành list
t_list[0] = 10    # Thay đổi phần tử
t = tuple(t_list) # Chuyển lại tuple
print(t)  # Output: (10, 2, 3)

4️⃣ Duyệt Tuple (Loop)

Dùng for để duyệt qua các phần tử:

t = ("apple", "banana", "cherry")
for item in t:
    print(item)

Duyệt tuple bằng **enumerate()**

for index, value in enumerate(t):
    print(f"Index {index}: {value}")

5️⃣ Toán tử với Tuple

Nối tuple (**+**)

t1 = (1, 2, 3)
t2 = (4, 5, 6)
t3 = t1 + t2
print(t3)  # Output: (1, 2, 3, 4, 5, 6)

Lặp lại tuple (*****)

t = (1, 2) * 3
print(t)  # Output: (1, 2, 1, 2, 1, 2)

6️⃣ Các hàm hữu ích với Tuple

Độ dài của tuple

t = (1, 2, 3, 4, 5)
print(len(t))  # Output: 5

Tìm giá trị lớn nhất, nhỏ nhất, tổng

t = (10, 5, 20, 8)
print(max(t))  # Output: 20
print(min(t))  # Output: 5
print(sum(t))  # Output: 43

Đếm số lần xuất hiện

t = (1, 2, 2, 3, 3, 3)
print(t.count(3))  # Output: 3 (Số lần 3 xuất hiện)

Tìm chỉ mục phần tử

t = (10, 20, 30, 40)
print(t.index(30))  # Output: 2 (Vị trí của số 30)

7️⃣ Unpacking Tuple

Có thể gán nhiều biến từ một tuple cùng lúc:

t = (1, 2, 3)
a, b, c = t
print(a)  # Output: 1
print(b)  # Output: 2
print(c)  # Output: 3

Unpacking với dấu *****

t = (1, 2, 3, 4, 5)
a, *b, c = t
print(a)  # Output: 1
print(b)  # Output: [2, 3, 4]
print(c)  # Output: 5

8️⃣ Tuple vs List: Khi nào nên dùng Tuple?

Tính năngTupleList
Thay đổi giá trị❌ Không thể thay đổi✅ Có thể thay đổi
Hiệu suất✅ Nhanh hơn (do bất biến)❌ Chậm hơn
Dùng làm key trong dictionary✅ Có thể❌ Không thể
Sử dụng khi nào?Dữ liệu không thay đổiDữ liệu cần thay đổi
👉 Dùng **tuple** khi dữ liệu không cần thay đổi và muốn tối ưu hiệu suất.

if **name** == “**main**“

Ý nghĩa

Trong Python, mỗi tập tin .py có một biến đặc biệt gọi là __name__:

  • Nếu tập tin được chạy trực tiếp, __name__ sẽ là "__main__".
  • Nếu tập tin được import vào file khác, __name__ sẽ là tên file đó. Giả sử ta có file **main.py**:
print(__name__)  # Output: "__main__"

Dùng if **name** == “**main**” để kiểm tra

Giả sử có file **module.py**:

def greet():
    print("Hello from module!")
if __name__ == "__main__":
    print("This will run only if module.py is executed directly.")

Khi chạy **python module.py**:

This will run only if module.py is executed directly.

Khi import **module.py** vào file khác:

import module
module.greet()  # Output: "Hello from module!"

Ứng dụng thực tế

🔹 Chạy code chỉ khi script được chạy trực tiếp

def main():
    print("This script is running directly!")
if __name__ == "__main__":
    main()

✅ Giúp tách biệt phần chạy chính khỏi code logic.

🔹 Viết script có thể import mà không bị chạy code ngoài ý muốn

File **math_utils.py**

def add(a, b):
    return a + b
if __name__ == "__main__":
    print(add(3, 4))  # Chỉ chạy khi file này được chạy trực tiếp

📌 Khi dùng import trong file khác (**import math_utils**), print(add(3, 4)) sẽ không chạy.

Dictionary

Dictionary (**dict**) là một kiểu dữ liệu trong Python lưu trữ cặp key-value. Nó tương tự như một bảng tra cứu, trong đó mỗi key là duy nhất và trỏ đến một giá trị.

1️⃣ Khai báo Dictionary

# Cách khai báo dictionary
student = {
    "name": "Alice",
    "age": 25,
    "city": "New York"
}
print(student)
# Output: {'name': 'Alice', 'age': 25, 'city': 'New York'}

Key có thể là: str, int, tupleValue có thể là: bất kỳ kiểu dữ liệu nào (int, list, dict, tuple, v.v.)

2️⃣ Truy cập phần tử

print(student["name"])  # Output: Alice
print(student["age"])   # Output: 25

📌 Nếu key không tồn tại, sẽ báo lỗi **KeyError**:

print(student["gender"])  # ❌ Lỗi: KeyError

Dùng **.get()** để tránh lỗi:

print(student.get("gender", "Unknown"))  
# Output: Unknown (trả về giá trị mặc định)

3️⃣ Thêm, sửa, xóa phần tử

🔹 Thêm hoặc cập nhật giá trị

student["age"] = 26  # Cập nhật giá trị
student["gender"] = "Female"  # Thêm key mới
print(student)
# Output: {'name': 'Alice', 'age': 26, 'city': 'New York', 'gender': 'Female'}

🔹 Xóa phần tử

del student["city"]  # Xóa key 'city'
print(student)
# Output: {'name': 'Alice', 'age': 26, 'gender': 'Female'}

Dùng **.pop()** để lấy giá trị trước khi xóa:

python
CopyEdit
age = student.pop("age")
print(age)  # Output: 26
print(student)  # Output: {'name': 'Alice', 'gender': 'Female'}

Xóa tất cả phần tử

student.clear()
print(student)  # Output: {}

4️⃣ Duyệt Dictionary

🔹 Duyệt qua keys

for key in student:
    print(key, "->", student[key])

🔹 Duyệt qua values

for value in student.values():
    print(value)

🔹 Duyệt qua key-value

for key, value in student.items():
    print(f"{key}: {value}")

5️⃣ Các phương thức hữu ích

student = {
    "name": "Bob",
    "age": 30,
    "city": "London"
}
print(student.keys())    # dict_keys(['name', 'age', 'city'])
print(student.values())  # dict_values(['Bob', 30, 'London'])
print(student.items())   # dict_items([('name', 'Bob'), ('age', 30), ('city', 'London')])

Kiểm tra key có tồn tại không

print("name" in student)  # Output: True
print("salary" in student)  # Output: False

Copy dictionary

new_student = student.copy()

6️⃣ Dictionary lồng nhau (Nested Dictionary)

students = {
    "Alice": {"age": 25, "city": "New York"},
    "Bob": {"age": 30, "city": "London"}
}
print(students["Alice"]["age"])  # Output: 25

7️⃣ Dictionary Comprehension

Tạo dictionary từ list

numbers = [1, 2, 3, 4, 5]
squares = {x: x**2 for x in numbers}
print(squares)  # Output: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

Lọc dictionary

filtered = {k: v for k, v in student.items() if k != "age"}
print(filtered)  # Output: {'name': 'Bob', 'city': 'London'}

Classes and Objects

Python là một ngôn ngữ lập trình hướng đối tượng (OOP), trong đó lớp (class) là một mẫu thiết kếđối tượng (object) là một thể hiện (instance) của lớp đó.

1️⃣ Định nghĩa một Class và tạo Object

class Person:
    def __init__(self, name, age):
        self.name = name  # Thuộc tính (attribute)
        self.age = age
    def greet(self):  # Phương thức (method)
        print(f"Hello, my name is {self.name} and I am {self.age} years old.")
# Tạo đối tượng (Object)
p1 = Person("Alice", 25)
# Gọi phương thức
p1.greet()
# Output: Hello, my name is Alice and I am 25 years old.

Giải thích:

  • class Person: → Định nghĩa lớp Person.
  • __init__(self, name, age) → Hàm khởi tạo (constructor) để thiết lập giá trị ban đầu.
  • self.nameself.age → Thuộc tính (attribute) của đối tượng.
  • greet(self) → Phương thức (method) của lớp.
  • p1 = Person("Alice", 25) → Tạo một object p1 từ class Person.
  • p1.greet() → Gọi method.

2️⃣ Thuộc tính và Phương thức trong Class

🔹 Thuộc tính (Attributes)

class Car:
    def __init__(self, brand, color):
        self.brand = brand  # Biến thuộc tính
        self.color = color
# Tạo đối tượng
car1 = Car("Toyota", "Red")
print(car1.brand)  # Output: Toyota
print(car1.color)  # Output: Red

🔹 Phương thức (Methods)

class Dog:
    def __init__(self, name):
        self.name = name
    def bark(self):  # Phương thức
        print(f"{self.name} is barking!")
dog1 = Dog("Buddy")
dog1.bark()  # Output: Buddy is barking!

3️⃣ Phạm vi của thuộc tính: **public**, **private**, **protected**

Phạm viCú phápÝ nghĩa
Publicself.nameTruy cập từ bất cứ đâu
Protectedself._nameTruy cập nội bộ hoặc lớp con
Privateself.__nameChỉ truy cập bên trong class

Ví dụ:

class Employee:
    def __init__(self, name, salary):
        self.name = name        # Public
        self._department = "IT" # Protected
        self.__salary = salary  # Private
    def show_salary(self):
        print(f"Salary: {self.__salary}")
e = Employee("John", 5000)
print(e.name)         # ✅ Output: John (public)
print(e._department)  # ✅ Output: IT (protected, vẫn truy cập được)
print(e.__salary)     # ❌ Lỗi: AttributeError (private)

Cách truy cập biến private (không khuyến khích):

 print(e._Employee__salary)  # Output: 5000

4️⃣ Kế thừa (Inheritance)

Kế thừa cho phép một lớp mới (con) sử dụng lại thuộc tính và phương thức từ lớp cha.

class Animal:
    def speak(self):
        print("Animal is making a sound")
# Lớp Dog kế thừa từ Animal
class Dog(Animal):
    def speak(self):  # Ghi đè phương thức (Overriding)
        print("Woof! Woof!")
dog = Dog()
dog.speak()  # Output: Woof! Woof!

5️⃣ Ghi đè phương thức (**Method Overriding**)

Khi lớp con định nghĩa lại một phương thức của lớp cha.

class Parent:
    def show(self):
        print("This is Parent class")
class Child(Parent):
    def show(self):
        print("This is Child class")
c = Child()
c.show()  # Output: This is Child class

6️⃣ Gọi phương thức lớp cha với **super()**

Dùng super() để gọi phương thức của lớp cha.

class Parent:
    def __init__(self, name):
        self.name = name
    def show(self):
        print(f"Name: {self.name}")
class Child(Parent):
    def __init__(self, name, age):
        super().__init__(name)  # Gọi constructor của lớp cha
        self.age = age
    def show(self):
        super().show()  # Gọi phương thức lớp cha
        print(f"Age: {self.age}")
c = Child("Alice", 25)
c.show()
# Output:
# Name: Alice
# Age: 25

7️⃣ Lớp Trừu Tượng (**Abstract Class**)

Dùng để ép buộc lớp con phải triển khai một số phương thức nhất định.

from abc import ABC, abstractmethod
class Animal(ABC):
    @abstractmethod
    def make_sound(self):
        pass  # Lớp con bắt buộc phải cài đặt phương thức này
class Dog(Animal):
    def make_sound(self):
        print("Woof! Woof!")
dog = Dog()
dog.make_sound()  # Output: Woof! Woof!

8️⃣ **__str__()** để in Object

Hàm __str__() giúp tùy chỉnh cách object hiển thị khi gọi **print()**.

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __str__(self):
        return f"Person(name={self.name}, age={self.age})"
p = Person("Bob", 30)
print(p)  # Output: Person(name=Bob, age=30)