Tóm tắt buổi trước

Trong buổi vừa Live vừa rồi, chúng ta học qua được các khái niệm về các quy tắt trong Python (Language Semantics) – Đây là phần tạo nên sự khác biệt giữa Python và các ngôn ngữ bậc cao khác. Nói không ngoa chứ chưa học phần này là chưa biết về Python vậy nên các bạn nhớ đọc qua nếu chưa coi nhen:

Language Sematics post

Còn trong buổi hôm nay ta sẽ học tiếp về một chủ để quan trọng không kém, là một trong những chủ đề đặt nền móng cho kỹ năng lập trình sau này của chúng ta: Scalar Types – Các kiểu dữ liệu cơ bản. Sau đó chúng ta sẽ học về những kỹ thuật xoay xung quanh các kiểu dữ liệu này

🔴 Buổi Live ngày 5:

🍀 Scclar Types – Các kiểu dữ cơ bản

Python có một tập nhỏ các kiểu dữ liệu tích hợp để xử lý dữ liệu số, chuỗi, giá trị Boolean (True hoặc False) và ngày và giờ (datetime). Các loại “giá trị đơn” này đôi khi được gọi là scalar types hay scalars.

Bảng sau đây cho biết các kiểu dữ liệu tiêu chuẩn

🔥 Numeric types

Các kiểu chính là intfloat.

In [53]: ival = 17239871

In [54]: ival ** 6
Out[54]: 26254519291092456596965462913230729701102721

float đôi khi được ký hiệu bằng ký hiệu khoa học (scientific notation):

In [55]: fval = 7.243

In [56]: fval2 = 6.78e-5

Riêng hàm chia thì kết quả trả về luôn chuyển thành kiểu float

In [57]: 3 / 2
Out[57]: 1.5

Còn nếu muốn chia ra số nguyên thì làm như sau:

In [58]: 3 // 2
Out[58]: 1

Fun fact: Kiểu int không có giới hạn và miễn là bộ nhớ bạn cho phép thì cỡ nào cũng chơi.

link

🔥 String literals

Dịch sát nghĩa phải là “Chuỗi ký tự” nhưng để gọn thì mình gọi là “Chuỗi” nhé

🔥 Nháy đơn hay Nháy kép

Nhiều người sử dụng Python vì những khả năng xử lý chuỗi đã được tích hợp sẵn của nó. Bạn có thể viết chuỗi bằng cách sử dụng dấu ngoặc đơn ' hoặc dấu ngoặc kép " (dấu ngoặc kép thường được ưa thích hơn)

a = 'one way of writing a string'
b = "another way"

Kiểu chuỗi của Python được ký hiệu là str.

Đối với các chuỗi có xuống dòng, bạn có thể sử dụng dấu ''' hoặc """

c = """
This is a longer string that
spans multiple lines
"""

Có thể bạn chưa biết nhưng dù nhìn biến c chỉ chứa có 2 dòng nhưng Python đang xác định nó gồm ba dòng gồm:

  • Ngắt dòng sau """
  • Ngắt dòng sau thatlines

Chúng ta có thể đếm các ký tự dòng mới bằng phương thức count

In [60]: c.count("\n")
Out[60]: 3

🎯 Imutable String

Như đã nói ở trên Chuỗi Python là dạng bất biến; bạn không thể sửa đổi chuỗi trong quá trình biên dịch:

In [61]: a = "this is a string"

In [62]: a[10] = "f"
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-62-3b2d95f10db4> in <module>
----> 1 a[10] = "f"
TypeError: 'str' object does not support item assignment

👀 Để hiểu thông báo lỗi này, hãy đọc từ dưới lên:

  • Chúng ta đã cố gắng thay thế ký tự (the “item”) ở vị trí 10 bằng chữ “f”,
  • , nhưng điều này không được phép đối với các đối tượng chuỗi (TypeError).

🍀 Nếu cần sửa đổi chuỗi, chúng ta phải sử dụng hàm hoặc phương thức tạo chuỗi mới, chẳng hạn như phương thức replace:

In [63]: b = a.replace("string", "longer string")

In [64]: b
Out[64]: 'this is a longer string'

Sau khi thực hiện thao tác này, biến a vẫn không thay đổi:

In [65]: a
Out[65]: 'this is a string'

🎯 Hàmstr( )

Nhiều đối tượng Python có thể được chuyển đổi thành chuỗi bằng cách sử dụng hàm str( ):

In [66]: a = 5.6

In [67]: s = str(a)

In [68]: type(s)
str

🎯 Tính chất

Chuỗi là một trình tự các ký tự Unicode và do đó có thể thao tác giống như các trình tự khác, chẳng hạn như list và tuple:

In [69]: s = "python"

In [70]: list(s)
Out[70]: ['p', 'y', 't', 'h', 'o', 'n']

In [71]: s[:3]
Out[71]: 'pyt'

Cú pháp s[:3] được gọi là slicing và được nhiều sau này khi dụng tới DataFrame.

Trong df thì việc slicing sẽ được dùng bằng hàm .loc.iloc

Lấy ví dụ sau đâ: “top 50 bài hát trên Spotify năm 2021”

# Since indexing starts at 0, the rows from 1-5 are to be returned
df.loc[1:5, :]

# Slicing columns using column names
df.loc[:, "artist_name":"popularity"]

# Slicing using both rows and columns
df.loc[0:9, "id":"popularity"]

🎯 Blackslash character (dấu ngắt \)

Ký tự dấu gạch chéo ngược \ được sử dụng để chỉ định các ký tự đặc biệt như ký tự dòng mới \n hoặc ký tự Unicode.

In [72]: s = "12\\34"

In [73]: print(s)
12\34

Nếu bạn có một chuỗi với nhiều dấu gạch chéo ngược và không có ký tự đặc biệt, bạn có thể thấy điều này hơi khó chịu. May mắn là bạn có thể đặt trước dấu ngoặc kép đầu tiên của chuỗi bằng r, nghĩa là raw

Trong tiếng Việt có bỏ dấu thì bắt buộc cần dùng r để hiểu được dấu câu

In [74]: s = r"this\has\no\special\characters"

In [75]: s
Out[75]: 'this\\has\\no\\special\\characters'

🎯 Concatenate strings – Nối chuỗi

Ta có thể nối hai chuỗi với nhau sẽ tạo ra một chuỗi mới. Ví dụ:

In [76]: a = "this is the first half "

In [77]: b = "and this is the second half"

In [78]: a + b
Out[78]: 'this is the first half and this is the second half'

Output:

this is the first half and this is the second half

🎯 Hàm .format() – Định dạng chuỗi

Phương thức format() có thể được sử dụng tham số định dạng-thay thế chuỗi vào trong chuỗi và tạo ra một chuỗi mới.

Có thể bạn chưa biết format() thuộc một dự án open-source tên là PyFormat và được cộng đồng đóng góp xây dựng rất nhiều.

PyFormat ra đời nhằm thay thế cách format chuỗi cũ bằng toán tử %t %s %f tham chiếu tương ứng datatypes int str float

Official Page

⭐ Xét ví dụ sau:

In [79]: template = "{0:.2f} {1:s} are worth US${2:d}"

Trong chuỗi này:

  • {0:.2f} Định dạng tham số đầu kiểu float với hai chữ số thập phân.
  • {1:s} Định dạng tham số thứ hai kiểu str.
  • {2:d} Định dạng tham số thứ ba kiểu int.

▶ Để thay thế các tham số cho các tham số định dạng này, chúng ta truyền một chuỗi các tham số vào phương thức format(). Ví dụ:

In [80]: template.format(88.46, "Argentine Pesos", 1)
Out[80]: '88.46 Argentine Pesos are worth US$1'

Python 3.6 đã giới thiệu một tính năng mới gọi là f-string (viết tắt của formatted string literals) có thể giúp việc tạo các chuỗi được định dạng trở nên thuận tiện hơn.

Để tạo một f-string, bạn cần viết ký tự f ngay trước chuỗi. Trong chuỗi, bạn có thể sử dụng dấu ngoặc nhọn {} để bọc các biến sẽ được thay thế. Khi biên dịch, các biến sẽ được thay thế bằng giá trị của chúng.

In [81]: amount = 10

In [82]: rate = 88.46

In [83]: currency = "Pesos"

In [84]: result = f"{amount} {currency} is worth US${amount / rate}"

Quay lại ví dụ trên, các định dạng chuỗi có thể được thêm sau mỗi biểu thức bằng sau:

In [85]: f"{amount} {currency} is worth US${amount / rate:.2f}"
Out[85]: '10 Pesos is worth US$0.11'

Dân kỹ thuật còn gọi là String Injection.

f-string nhanh gọn thiệt đó nhưng trên thực tế thì người ta vẫn chuộng dùng kiểu format( ) hơn vì lý do SQL Injection Attack

Chủ đề về định dạng chuỗi thật ra rất sâu rộng, vì phần lớn dữ liệu chúng ta xử lý hằng ngày đề là text hết mà.

Để đọc thêm thì đây: official Python document

🔥 Bytes và Unicode

Bytes là một kiểu dữ liệu immutable, đại diện cho một chuỗi các giá trị byte. 1 byte=8 bits và mỗi ký tự dùng 8 bits để biểu thị (trong bảng mã ASCII)

Chúng được sử dụng để biểu diễn dữ liệu nhị phân, chẳng hạn như tệp hình ảnh, tệp âm thanh

Bytes cũng có thể được sử dụng để biểu diễn văn bản được mã hóa, chẳng hạn như mã ASCII, UTF-8 và UTF-16.

Okay mình sẽ không đi sâu vào vấn đề mã hóa này. Các bạn chỉ cần hiểu là từ Python3.0 trở đi thì mã Unicode đã mặc định trở thành bộ giải mã cho các văn bản ASCII và non-ASCII. Và điều này liên quan mật thiết tới tiếng Việt chung ta.

Hoan hô Python3.0 🥳

Bạn có thể vọc một số đoạn code sau:

val = "español"
# val = "Mình là Bò Cười Làm Data"
val

val_utf8 = val.encode("utf-8")
print(val_utf8)
type(val_utf8)

🔥 Booleans

Hai toán tử duy nhất của Booleans là TrueFalse

Mình tin là ai cũng sẽ biết tới các mệnh đề đề logic Hợp, Giao, Bù, Kéo theo học hồi năm lớp 9. Bản thân Lập trình là từ Toán học nên tất nhiên các lý thuyết vẫn đúng và áp dụng.

Ví dụ phủ định của Đúng là Sai thì trong code sẽ là

In [99]: a = True

In [100]: b = False

In [101]: not a
Out[101]: False

In [102]: not b
Out[102]: True

Hay “Một nửa của sự thật cũng không phải sự thật” 😂

In [95]: True and True
Out[95]: True

In [96]: False or True
Out[96]: True

Đặc biệt xíu thì với lập trình True được đại diện bằng 1 và ngược lại False đại diện bằng 0

In [97]: int(False)
Out[97]: 0

In [98]: int(True)
Out[98]: 1

🔥 Type casting – Ép kiểu

4 kiểu dữ liệu chính str , bool , intfloat để có các hàm để ép kiểu qua lại với nhau

In [103]: s = "3.14159"

In [104]: fval = float(s)

In [105]: type(fval)
Out[105]: float

In [106]: int(fval)
Out[106]: 3

In [107]: bool(fval)
Out[107]: True

In [108]: bool(0)
Out[108]: False

Nếu ta ép kiểu bất kỳ giá trị nào khác 0 sang bool thì nó sẽ trả về True hết.

Ta cũng không thể ép chuỗi văn bản thành kiểu số được

🔥 None

None là đại diện của nulln/a trong Excel.

In [109]: a = None

In [110]: a is None
Out[110]: True

In [111]: b = 5

In [112]: b is not None
Out[112]: True

Ta có thể ràng buộc điều kiện non-None vào trong hàm như sau:

def add_and_maybe_multiply(a, b, c=None):
    result = a + b

    if c is not None:
        result = result * c

    return result

🎯 NaN và Empty trong DataFrame

Trong DataFrame có hơi đặc biệt là ta sẽ làm việc với empty và NaN.

Nhưng

Rõ ràng DF chưa NaN thì không được tính rỗng.

Để check NaN: isna()

🔥 Dates and times

Để làm việc với time series ta dùng module datetime vì nó sẽ cung cấp cho ta các kiểu dữ liệu datetime datetime tương ứng với từng trường hợp sử dụng và chuyển đổi.

In [113]: from datetime import datetime, date, time

In [114]: dt = datetime(2011, 10, 29, 20, 30, 21)

In [115]: dt.day
Out[115]: 29

In [116]: dt.minute
Out[116]: 30

Ta có thể định dạng bằng hàm strftime như sau:

In [119]: dt.strftime("%Y-%m-%d %H:%M")
Out[119]: '2011-10-29 20:30'

Hoặc convert từ str sang datatime

In [120]: datetime.strptime("20091031", "%Y%m%d")
Out[120]: datetime.datetime(2009, 10, 31, 0, 0)

%Y%m%d là mã định dạng, full danh sách tại đây:

🎯 Immutable datetimes objects

Bản chất datetime là một đối tượng bất biến nên khi ta aggreate hay grouping nói cách khác là modify nó thì Python sẽ tạo ra một đối tượng mới

▶ Ví dụ ta dùng replace để thay đổi thành phần của đối tượng dt đã tạo ở trên:

In [121]: dt_hour = dt.replace(minute=0, second=0)

In [122]: dt_hour
Out[122]: datetime.datetime(2011, 10, 29, 20, 0)

Kiểm tra lại thử:

In [123]: dt
Out[123]: datetime.datetime(2011, 10, 29, 20, 30, 21)

▶ Khi trừ hai đối tượng datetime với nhau ta tạo ra một kiểu dữ liệu mới là datetime.timedelta

In [124]: dt2 = datetime(2011, 11, 15, 22, 30)

In [125]: delta = dt2 - dt

In [126]: delta
Out[126]: datetime.timedelta(days=17, seconds=7179)

In [127]: type(delta)
Out[127]: datetime.timedelta

Kết quả trả về timedelta(17, 7179) tương ứng 17 ngày và 7,179 giây

▶ Nhưng khi ta cộng 2 ngày lại với nhau thì nó sẽ trả về đối tượng datetime

In [128]: dt
Out[128]: datetime.datetime(2011, 10, 29, 20, 30, 21)

In [129]: dt + delta
Out[129]: datetime.datetime(2011, 11, 15, 22, 30)

Lời kết

Mặc dù các kiểu dữ liệu cơ bản (scalar types) ở các ngôn ngữ khác nhau có thể khác ở một vài điểm nào đó (như ký hiệu, max_volume, min_volume, ..) nhưng về tổng thể thì bất kỳ ngôn ngữ nào đều có mặt tụi nó vì đây là các đối tượng trong toán học cơ sở.

Với tầm quan trọng như vậy nên chúng ta sẽ gặp nó xuyên suốt quá trình lập trình Python, và hầu như việc phân tích dữ liệu chung quy cùng là phân tích dựa trên những kiểu dữ liệu này.

Hẹn gặp các bạn và buổi Livestream kế tiếp nhé (8:00 PM – T3 và CN hằng tuần)

Các kênh cộng đồng của mình

  • Facebook: https://www.facebook.com/bocuoilamdata
  • Youtube: https://www.youtube.com/@CarrY4U_VN
  • Website: https://carry4u.org/

© Bản quyền thuộc về CarrY4U và Bò Cười Làm Data
© Copyright by CarrY4U and bocuoilamdata ☞ Do not Reup”