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:
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à int và float.
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.
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 that và lines
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 và .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 intstrfloat
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à.
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à True và False
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 , int và float để 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 null và n/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 datetimedate và time 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
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)