Python: Các kiểu dữ liệu cơ bản trong Python


Khóa học qua video:
Lập trình Python All Lập trình C# All SQL Server All Lập trình C All Java PHP HTML5-CSS3-JavaScript
Đăng ký Hội viên
Tất cả các video dành cho hội viên

Mục lục bài viết:

  • Số nguyên
  • Số dấu phẩy động
  • Số phức
  • Dây
    • Trình tự thoát trong chuỗi
    • Chuỗi thô
    • Chuỗi ba dấu ngoặc kép
  • Kiểu Boolean, Ngữ cảnh Boolean và "Độ tin cậy"
  • Chức năng tích hợp sẵn
    • môn Toán
    • Chuyển đổi loại
    • Lặp lại và Trình lặp lại
    • Loại dữ liệu tổng hợp
    • Lớp, Thuộc tính và Kế thừa
    • Đầu ra đầu vào
    • Biến, Tham chiếu và Phạm vi
    • Điều khoản khác
  • Phần kết luận

Bây giờ bạn đã biết cách tương tác với trình thông dịch Python và thực thi mã Python . Đã đến lúc đào sâu vào ngôn ngữ Python. Đầu tiên là thảo luận về các kiểu dữ liệu cơ bản được tích hợp trong Python.

Đây là những gì bạn sẽ học trong hướng dẫn này:

  • Bạn sẽ tìm hiểu về một số kiểu số, chuỗi và Boolean cơ bản được tích hợp trong Python. Đến cuối hướng dẫn này, bạn sẽ làm quen với các đối tượng của các loại này trông như thế nào và cách biểu diễn chúng.
  • Bạn cũng sẽ có cái nhìn tổng quan về các hàm tích hợp của Python . Đây là những đoạn mã được viết sẵn mà bạn có thể gọi để làm những việc hữu ích. Bạn đã thấy được xây dựng trong print()chức năng , nhưng có rất nhiều người khác.

Số nguyên

Trong Python 3, thực sự không có giới hạn về độ dài của một giá trị số nguyên. Tất nhiên, nó bị hạn chế bởi dung lượng bộ nhớ mà hệ thống của bạn có, nhưng ngoài ra, một số nguyên có thể dài miễn là bạn cần:

>>>
>>> print(123123123123123123123123123123123123123123123123 + 1)
123123123123123123123123123123123123123123123124

Python diễn giải một chuỗi các chữ số thập phân không có tiền tố nào là số thập phân:

>>>
>>> print(10)
10

Các chuỗi sau có thể được thêm vào trước một giá trị số nguyên để chỉ ra một cơ số khác 10:

Tiếp đầu ngữ Diễn dịch Căn cứ
0b(không + chữ thường 'b')
0B(không + chữ hoa 'B')
Nhị phân 2
0o(không + chữ thường 'o')
0O(không + chữ hoa 'O')
Bát phân số 8
0x(không + chữ thường 'x')
0X(không + chữ hoa 'X')
Hệ thập lục phân 16

Ví dụ:

>>>
>>> print(0o10)
8

>>> print(0x10)
16

>>> print(0b10)
2

Để biết thêm thông tin về các giá trị số nguyên có cơ số không phải thập phân, hãy xem các trang Wikipedia sau: Nhị phân , Bát phân và Thập lục phân .

Kiểu cơ bản của một số nguyên Python, bất kể cơ sở được sử dụng để chỉ định nó, được gọi là int:

>>>
>>> type(10)
<class 'int'>
>>> type(0o10)
<class 'int'>
>>> type(0x10)
<class 'int'>

Lưu ý: Đây là thời điểm tốt để đề cập rằng nếu bạn muốn hiển thị một giá trị khi đang ở trong phiên REPL, bạn không cần phải sử dụng print()hàm. Chỉ cần nhập giá trị tại >>>dấu nhắc và nhấn Entersẽ hiển thị giá trị đó:

>>>
>>> 10
10
>>> 0x10
16
>>> 0b10
2

Nhiều ví dụ trong loạt bài hướng dẫn này sẽ sử dụng tính năng này.

Lưu ý rằng điều này không hoạt động bên trong tệp kịch bản. Một giá trị tự xuất hiện trên một dòng trong tệp script sẽ không thực hiện bất cứ điều gì.

Số dấu phẩy động

Các floatloại bằng Python chỉ định một số dấu chấm động. floatcác giá trị được chỉ định bằng dấu thập phân. Theo tùy chọn, ký tự ehoặc Etheo sau là số nguyên dương hoặc âm có thể được thêm vào để chỉ định ký hiệu khoa học :

>>>
>>> 4.2
4.2
>>> type(4.2)
<class 'float'>
>>> 4.
4.0
>>> .2
0.2

>>> .4e7
4000000.0
>>> type(.4e7)
<class 'float'>
>>> 4.2e-4
0.00042

Lặn sâu: Biểu diễn dấu chấm động

Sau đây là một chút thông tin chuyên sâu hơn về cách Python biểu diễn nội bộ số dấu phẩy động. Bạn có thể dễ dàng sử dụng các số dấu phẩy động trong Python mà không cần hiểu chúng ở cấp độ này, vì vậy đừng lo lắng nếu điều này có vẻ quá phức tạp. Thông tin được trình bày ở đây trong trường hợp bạn tò mò.

Hầu hết tất cả các nền tảng đều biểu thị floatcác giá trị Python dưới dạng giá trị "độ chính xác kép" 64-bit, theo tiêu chuẩn IEEE 754 . Trong trường hợp đó, giá trị lớn nhất mà một số dấu phẩy động có thể có là khoảng 1,8 ⨉ 10 308 . Python sẽ chỉ ra một số lớn hơn số đó bởi chuỗi inf:

>>>
>>> 1.79e308
1.79e+308
>>> 1.8e308
inf

Gần nhất một số khác không thể bằng không là xấp xỉ 5,0 ⨉ 10 -324 . Bất cứ điều gì gần 0 hơn 0 thực sự là 0:

>>>
>>> 5e-324
5e-324
>>> 1e-325
0.0

Số dấu phẩy động được biểu diễn bên trong dưới dạng phân số nhị phân (cơ số 2). Hầu hết các phân số thập phân không thể được biểu diễn chính xác dưới dạng phân số nhị phân, vì vậy trong hầu hết các trường hợp, biểu diễn bên trong của một số dấu phẩy động là một giá trị gần đúng với giá trị thực. Trong thực tế, sự khác biệt giữa giá trị thực tế và giá trị được đại diện là rất nhỏ và thường không gây ra vấn đề đáng kể.

Đọc thêm: Để biết thêm thông tin về biểu diễn dấu phẩy động trong Python và các cạm bẫy tiềm ẩn liên quan, hãy xem Số học Dấu phẩy động : Vấn đề và Hạn chế trong tài liệu Python.

Số phức

Số phức được chỉ định như <real part>+<imaginary part>j. Ví dụ:

>>>
>>> 2+3j
(2+3j)
>>> type(2+3j)
<class 'complex'>

Dây

Chuỗi là chuỗi dữ liệu ký tự. Kiểu chuỗi trong Python được gọi str.

Các ký tự chuỗi có thể được phân tách bằng cách sử dụng dấu ngoặc kép hoặc đơn. Tất cả các ký tự giữa dấu phân cách mở và dấu phân cách đóng phù hợp là một phần của chuỗi:

>>>
>>> print("I am a string.")
I am a string.
>>> type("I am a string.")
<class 'str'>

>>> print('I am too.')
I am too.
>>> type('I am too.')
<class 'str'>

Một chuỗi trong Python có thể chứa bao nhiêu ký tự tùy thích. Giới hạn duy nhất là tài nguyên bộ nhớ của máy tính của bạn. Một chuỗi cũng có thể trống:

>>>
>>> ''
''

Điều gì sẽ xảy ra nếu bạn muốn bao gồm một ký tự trích dẫn như một phần của chính chuỗi? Động lực đầu tiên của bạn có thể là thử một cái gì đó như sau:

>>>
>>> print('This string contains a single quote (') character.')
SyntaxError: invalid syntax

Như bạn có thể thấy, điều đó không hoạt động quá tốt. Chuỗi trong ví dụ này sẽ mở ra bằng một dấu nháy đơn, vì vậy Python giả định dấu nháy đơn tiếp theo, dấu trong ngoặc đơn được dự định là một phần của chuỗi, là dấu phân cách đóng. Dấu ngoặc kép cuối cùng sau đó là một dấu ngoặc kép và gây ra lỗi cú pháp được hiển thị.

Nếu bạn muốn bao gồm một trong hai loại ký tự trích dẫn trong chuỗi, cách đơn giản nhất là phân tách chuỗi với loại còn lại. Nếu một chuỗi chứa một dấu ngoặc kép, hãy phân tách nó bằng dấu ngoặc kép và ngược lại:

>>>
>>> print("This string contains a single quote (') character.")
This string contains a single quote (') character.

>>> print('This string contains a double quote (") character.')
This string contains a double quote (") character.

Trình tự thoát trong chuỗi

Đôi khi, bạn muốn Python diễn giải một ký tự hoặc chuỗi ký tự trong một chuỗi theo cách khác. Điều này có thể xảy ra theo một trong hai cách:

  • Bạn có thể muốn loại bỏ cách diễn giải đặc biệt mà các ký tự nhất định thường được đưa ra trong một chuỗi.
  • Bạn có thể muốn áp dụng cách diễn giải đặc biệt cho các ký tự trong một chuỗi mà thường được hiểu theo nghĩa đen.

Bạn có thể thực hiện điều này bằng cách sử dụng \ký tự dấu gạch chéo ngược ( ). Một ký tự gạch chéo ngược trong một chuỗi chỉ ra rằng một hoặc nhiều ký tự theo sau nó phải được xử lý đặc biệt. (Đây được gọi là chuỗi ký tự thoát, vì dấu gạch chéo ngược khiến chuỗi ký tự tiếp theo "thoát" ý nghĩa thông thường của nó.)

Hãy xem cách này hoạt động như thế nào.

Loại bỏ ý nghĩa ký tự đặc biệt

Bạn đã thấy những vấn đề mà bạn có thể gặp phải khi cố gắng đưa các ký tự trích dẫn vào một chuỗi. Nếu một chuỗi được phân tách bằng các dấu nháy đơn, bạn không thể chỉ định trực tiếp một ký tự trích dẫn duy nhất như một phần của chuỗi vì đối với chuỗi đó, dấu nháy đơn có ý nghĩa đặc biệt — nó kết thúc chuỗi:

>>>
>>> print('This string contains a single quote (') character.')
SyntaxError: invalid syntax

Việc chỉ định một dấu gạch chéo ngược phía trước ký tự trích dẫn trong một chuỗi "thoát khỏi" nó và khiến Python loại bỏ ý nghĩa đặc biệt thông thường của nó. Sau đó, nó được hiểu đơn giản là một ký tự trích dẫn đơn theo nghĩa đen:

>>>
>>> print('This string contains a single quote (\') character.')
This string contains a single quote (') character.

Điều tương tự cũng hoạt động trong một chuỗi được phân tách bằng dấu ngoặc kép:

>>>
>>> print("This string contains a double quote (\") character.")
This string contains a double quote (") character.

Sau đây là bảng các chuỗi thoát khiến Python ngăn chặn cách diễn giải đặc biệt thông thường của một ký tự trong một chuỗi:


Trình tự thoát
Giải thích thông thường về
(các) ký tự sau dấu gạch chéo ngược
Diễn giải "Đã thoát"
\' Kết thúc chuỗi bằng dấu phân cách mở ngoặc kép Ký tự trích dẫn đơn ( ') theo nghĩa đen
\" Kết thúc chuỗi với dấu phân cách mở ngoặc kép Dấu ngoặc kép theo nghĩa đen ( ") ký tự
\newline Kết thúc dòng đầu vào Dòng mới bị bỏ qua
\\ Giới thiệu trình tự thoát Ký tự gạch chéo ngược theo nghĩa đen ( \)

Thông thường, một ký tự dòng mới kết thúc việc nhập dòng. Vì vậy, việc nhấn Entervào giữa một chuỗi sẽ khiến Python nghĩ rằng nó chưa hoàn chỉnh:

>>>
>>> print('a

SyntaxError: EOL while scanning string literal

Để chia nhỏ một chuỗi trên nhiều dòng, hãy thêm dấu gạch chéo ngược trước mỗi dòng mới và các dòng mới sẽ bị bỏ qua:

>>>
>>> print('a\
... b\
... c')
abc

Để bao gồm một dấu gạch chéo ngược theo nghĩa đen trong một chuỗi, hãy thoát khỏi nó bằng dấu gạch chéo ngược:

>>>
>>> print('foo\\bar')
foo\bar

Áp dụng ý nghĩa đặc biệt cho các ký tự

Tiếp theo, giả sử bạn cần tạo một chuỗi có chứa ký tự tab trong đó. Một số trình soạn thảo văn bản có thể cho phép bạn chèn ký tự tab trực tiếp vào mã của mình. Nhưng nhiều lập trình viên cho rằng thực hành kém, vì một số lý do:

  • Máy tính có thể phân biệt giữa ký tự tab và chuỗi ký tự khoảng trắng, nhưng bạn không thể. Đối với một người đọc mã, các ký tự tab và khoảng trắng không thể phân biệt được bằng mắt thường.
  • Một số trình soạn thảo văn bản được định cấu hình để tự động loại bỏ các ký tự tab bằng cách mở rộng chúng đến số khoảng cách thích hợp.
  • Một số môi trường Python REPL sẽ không chèn các tab vào mã.

Trong Python (và hầu như tất cả các ngôn ngữ máy tính phổ biến khác), một ký tự tab có thể được chỉ định bằng trình tự thoát \t:

>>>
>>> print('foo\tbar')
foo     bar

Chuỗi thoát \tkhiến tký tự mất đi ý nghĩa thông thường của nó, nghĩa đen t. Thay vào đó, sự kết hợp được hiểu là một ký tự tab.

Dưới đây là danh sách các chuỗi thoát khiến Python áp dụng nghĩa đặc biệt thay vì diễn giải theo nghĩa đen:

Trình tự thoát Diễn giải "Đã thoát"
\a Ký tự ASCII Bell ( BEL)
\b Ký tự ASCII Backspace ( BS)
\f Ký tự ASCII Formfeed ( FF)
\n Ký tự ASCII Linefeed ( LF)
\N{<name>} Ký tự từ cơ sở dữ liệu Unicode với <name>
\r Ký tự ASCII Carriage Return ( CR)
\t Ký tự Tab ngang ASCII ( TAB)
\uxxxx Ký tự Unicode có giá trị hex 16 bit xxxx
\Uxxxxxxxx Ký tự Unicode có giá trị hex 32 bit xxxxxxxx
\v Ký tự Tab dọc ASCII ( VT)
\ooo Ký tự có giá trị bát phân ooo
\xhh Ký tự có giá trị hex hh

Ví dụ:

>>>
>>> print("a\tb")
a    b
>>> print("a\141\x61")
aaa
>>> print("a\nb")
a
b
>>> print('\u2192 \N{rightwards arrow}')
→ →

Loại chuỗi thoát này thường được sử dụng để chèn các ký tự không được tạo sẵn từ bàn phím hoặc không dễ đọc hoặc không in được.

Chuỗi thô

Một ký tự chuỗi thô được đặt trước rhoặc R, chỉ định rằng các chuỗi thoát trong chuỗi được liên kết sẽ không được dịch. Ký tự gạch chéo ngược được để lại trong chuỗi:

>>>
>>> print('foo\nbar')
foo
bar
>>> print(r'foo\nbar')
foo\nbar

>>> print('foo\\bar')
foo\bar
>>> print(R'foo\\bar')
foo\\bar

Chuỗi ba dấu ngoặc kép

Có một cách khác để phân định chuỗi trong Python. Các chuỗi dấu ngoặc kép được phân định bằng cách khớp các nhóm gồm ba dấu ngoặc kép đơn hoặc ba dấu ngoặc kép. Các chuỗi thoát vẫn hoạt động trong các chuỗi được trích dẫn ba lần, nhưng các dấu ngoặc kép, dấu ngoặc kép và dòng mới có thể được đưa vào mà không cần thoát khỏi chúng. Điều này cung cấp một cách thuận tiện để tạo một chuỗi có cả dấu nháy đơn và dấu ngoặc kép trong đó:

>>>
>>> print('''This string has a single (') and a double (") quote.''')
This string has a single (') and a double (") quote.

Bởi vì các dòng mới có thể được bao gồm mà không cần thoát khỏi chúng, điều này cũng cho phép các chuỗi nhiều dòng:

>>>
>>> print("""This is a
string that spans
across several lines""")
This is a
string that spans
across several lines

Bạn sẽ thấy trong hướng dẫn sắp tới về Cấu trúc chương trình Python cách có thể sử dụng chuỗi ba dấu ngoặc kép để thêm nhận xét giải thích vào mã Python.

Kiểu Boolean, Ngữ cảnh Boolean và "Độ tin cậy"

Python 3 cung cấp kiểu dữ liệu Boolean . Các đối tượng kiểu Boolean có thể có một trong hai giá trị Truehoặc False:

>>>
>>> type(True)
<class 'bool'>
>>> type(False)
<class 'bool'>

Như bạn sẽ thấy trong các hướng dẫn sắp tới, các biểu thức trong Python thường được đánh giá trong ngữ cảnh Boolean, có nghĩa là chúng được hiểu để đại diện cho sự thật hoặc giả dối. Một giá trị đúng trong ngữ cảnh Boolean đôi khi được cho là "đúng" và một giá trị sai trong ngữ cảnh Boolean được cho là "giả". (Bạn cũng có thể thấy “falsy” được đánh vần là “falsey.”)

Tính “trung thực” của một đối tượng kiểu Boolean là hiển nhiên: các đối tượng Boolean ngang bằng Truelà true (đúng) và những đối tượng bằng là falsy False(false). Nhưng các đối tượng không phải Boolean cũng có thể được đánh giá trong ngữ cảnh Boolean và được xác định là đúng hay sai.

Bạn sẽ tìm hiểu thêm về cách đánh giá các đối tượng trong ngữ cảnh Boolean khi bạn gặp các toán tử logic trong hướng dẫn sắp tới về các toán tử và biểu thức trong Python.

Chức năng tích hợp sẵn

Trình thông dịch Python hỗ trợ nhiều hàm được tích hợp sẵn: 64, kể từ Python 3.6. Bạn sẽ đề cập đến nhiều vấn đề này trong các cuộc thảo luận sau, khi chúng xuất hiện trong ngữ cảnh.

Hiện tại, sau đây là một bản tổng quan ngắn gọn, chỉ để đưa ra cảm nhận về những gì hiện có. Xem tài liệu Python về các hàm tích hợp để biết thêm chi tiết. Nhiều mô tả sau đây đề cập đến các chủ đề và khái niệm sẽ được thảo luận trong các hướng dẫn trong tương lai.

môn Toán

Chức năng Sự miêu tả
abs() Trả về giá trị tuyệt đối của một số
divmod() Trả về thương và phần dư của phép chia số nguyên
max() Trả về giá trị lớn nhất trong số các đối số hoặc mục đã cho trong một đối số có thể lặp lại
min() Trả về giá trị nhỏ nhất trong số các đối số hoặc mục đã cho trong một đối số có thể lặp lại
pow() Tăng một số thành một lũy thừa
round() Làm tròn giá trị dấu phẩy động
sum() Tính tổng các mục của một tệp có thể lặp lại

Chuyển đổi loại

Chức năng Sự miêu tả
ascii() Trả về một chuỗi chứa một biểu diễn có thể in được của một đối tượng
bin() Chuyển đổi một số nguyên thành một chuỗi nhị phân
bool() Chuyển đổi một đối số thành một giá trị Boolean
chr() Trả về biểu diễn chuỗi ký tự được cung cấp bởi đối số số nguyên
complex() Trả về một số phức được tạo từ các đối số
float() Trả về một đối tượng dấu phẩy động được tạo từ một số hoặc chuỗi
hex() Chuyển đổi một số nguyên thành một chuỗi thập lục phân
int() Trả về một đối tượng số nguyên được tạo từ một số hoặc chuỗi
oct() Chuyển đổi một số nguyên thành một chuỗi bát phân
ord() Trả về biểu diễn số nguyên của một ký tự
repr() Trả về một chuỗi chứa một biểu diễn có thể in được của một đối tượng
str() Trả về phiên bản chuỗi của một đối tượng
type() Trả về kiểu của một đối tượng hoặc tạo một đối tượng kiểu mới

Lặp lại và Trình lặp lại

Chức năng Sự miêu tả
all() Trả về Truenếu tất cả các phần tử của một tệp có thể lặp lại là true
any() Trả về Truenếu bất kỳ phần tử nào của một tệp có thể lặp lại là đúng
enumerate() Trả về danh sách các bộ chứa các chỉ số và giá trị từ một tệp có thể lặp lại
filter() Lọc các phần tử từ một tệp có thể lặp lại
iter() Trả về một đối tượng trình lặp
len() Trả về chiều dài của một đối tượng
map() Áp dụng một chức năng cho mọi mục của một vật có thể lặp lại
next() Lấy mục tiếp theo từ một trình lặp
range() Tạo một loạt các giá trị số nguyên
reversed() Trả về một trình lặp ngược
slice() Trả về một sliceđối tượng
sorted() Trả về danh sách đã sắp xếp từ một danh sách có thể lặp lại
zip() Tạo một trình lặp để tổng hợp các phần tử từ các tệp lặp lại

Loại dữ liệu tổng hợp

Chức năng Sự miêu tả
bytearray() Tạo và trả về một đối tượng của bytearraylớp
bytes() Tạo và trả về một bytesđối tượng (tương tự như bytearray, nhưng không thể thay đổi)
dict() Tạo một dictđối tượng
frozenset() Tạo một frozensetđối tượng
list() Tạo một listđối tượng
object() Tạo một đối tượng mới lạ
set() Tạo một setđối tượng
tuple() Tạo một tupleđối tượng

Lớp, Thuộc tính và Kế thừa

Chức năng Sự miêu tả
classmethod() Trả về một phương thức lớp cho một hàm
delattr() Xóa một thuộc tính khỏi một đối tượng
getattr() Trả về giá trị của thuộc tính đã đặt tên của một đối tượng
hasattr() Trả về Truenếu một đối tượng có một thuộc tính nhất định
isinstance() Xác định xem một đối tượng có phải là một thể hiện của một lớp nhất định hay không
issubclass() Xác định xem một lớp có phải là lớp con của một lớp nhất định hay không
property() Trả về giá trị thuộc tính của một lớp
setattr() Đặt giá trị của thuộc tính được đặt tên của một đối tượng
super() Trả về một đối tượng proxy mà phương thức ủy quyền gọi đến lớp cha hoặc lớp anh chị em

Đầu ra đầu vào

Chức năng Sự miêu tả
format() Chuyển đổi một giá trị thành một biểu diễn được định dạng
input() Đọc đầu vào từ bảng điều khiển
open() Mở tệp và trả về đối tượng tệp
print() In dòng văn bản hoặc bảng điều khiển

Biến, Tham chiếu và Phạm vi

Chức năng Sự miêu tả
dir() Trả về danh sách các tên trong phạm vi cục bộ hiện tại hoặc danh sách các thuộc tính đối tượng
globals() Trả về một từ điển đại diện cho bảng ký hiệu chung hiện tại
id() Trả về danh tính của một đối tượng
locals() Cập nhật và trả về một từ điển đại diện cho bảng ký hiệu cục bộ hiện tại
vars() Trả về __dict__thuộc tính cho một mô-đun , lớp hoặc đối tượng

Điều khoản khác

Chức năng Sự miêu tả
callable() Trả về Truenếu đối tượng xuất hiện có thể gọi được
compile() Biên dịch nguồn thành mã hoặc đối tượng AST
eval() Đánh giá một biểu thức Python
exec() Triển khai thực thi động mã Python
hash() Trả về giá trị băm của một đối tượng
help() Gọi hệ thống trợ giúp tích hợp sẵn
memoryview() Trả về một đối tượng dạng xem bộ nhớ
staticmethod() Trả về một phương thức tĩnh cho một hàm
__import__() Được mời bởi importtuyên bố

Phần kết luận

Trong hướng dẫn này, bạn đã tìm hiểu về các kiểu dữ liệu và chức năng tích hợp sẵn mà Python cung cấp.

Các ví dụ được đưa ra cho đến nay đều có thao tác và chỉ hiển thị các giá trị không đổi. Trong hầu hết các chương trình, bạn thường muốn tạo các đối tượng thay đổi giá trị khi chương trình thực thi.

Hãy xem hướng dẫn tiếp theo để tìm hiểu về các biến Python .

» Tiếp: Bố cục PyQt: Tạo các ứng dụng GUI chuyên nghiệp
« Trước: Cách xây dựng một ứng dụng GUI Python với wxPython
Khóa học qua video:
Lập trình Python All Lập trình C# All SQL Server All Lập trình C All Java PHP HTML5-CSS3-JavaScript
Đăng ký Hội viên
Tất cả các video dành cho hội viên
Copied !!!