(91) 350-9520 support@omarine.org M-F: 7 AM - 7 PM; Weekends: 9 AM - 5 PM

Lập trình Web: Python: Ngôn ngữ lập trình Python

Chào mừng năm mới 2018,

Trong đầu năm nay chúng ta sẽ bước vào lập trình Web. Mục tiêu là có đủ kỹ năng để xây dựng trang Web, quảng bá sản phẩm, dịch vụ, thậm chí là biểu diễn một ngôn ngữ lập trình mới hay một chương trình trí tuệ nhân tạo trên nền tảng Web, trong thế giới mà người ta gọi là Internet vạn vật.

Lập trình Web không khó như viết phần mềm desktop, nhưng phụ thuộc nhiều hơn vào các qui tắc đặc thù của nền tảng. Có một tấn tài liệu về Python, thêm một tấn Django và khoảng năm tạ cho Oscar để xây dựng một cửa hàng trực tuyến (làm chủ kỹ thuật để sản xuất hàng loạt hoặc phát triển backend). Đó là chưa kể đến css, html, js và một hệ cơ sở dữ liệu như MySQL.

Tuy nhiên, nếu kết hợp đọc tài liệu với tùy biến các module tham khảo thì khối lượng công việc sẽ giảm đi đáng kể.

Hai ngôn ngữ lập trình phía server thông dụng hiện nay là Python và PHP. Tương ứng với chúng là Django – một framework lập trình Web với ngôn ngữ Python, và WordPress – một hệ CMS với ngôn ngữ PHP. Chúng ta sẽ xem xét cả hai với kết quả thực hành là xây dựng cửa hàng trực tuyến.

Nội dụng chính trong loạt bài này như sau:

I/ Python:

  1. Ngôn ngữ lập trình Python
  2. Viết một chương trình thăm dò ý kiến sử dụng Django
  3. Xây dựng cửa hàng trực tuyến với Oscar-Paypal

II/ PHP

  1. Tùy biến Theme trong WordPress
  2. Giả lập một công đoạn của cửa hàng trực tuyến: Viết một plugin tạo menu quản trị để đặt và lựa chọn, xây dựng post tùy biến để quảng bá sản phẩm.
  3. Tham khảo WooCommerce với storefront

Ngôn ngữ lập trình Python

Có hai phiên bản chính là Python 2 và Python 3. Hiện nay các nền tảng Web dựa trên Python chủ yếu sử dụng Python 3, do đó chúng ta chỉ xét tới Python 3.

1. Chương trình Hello World

print ( 'Hello, World' )

Giả sử tệp mã nguồn có tên là p3.py. Chương trình được chạy như sau:

python p3.py

Nếu muốn chương trình chạy như chương trình thông thường, bạn thêm #!/usr/bin/env python vào đầu chương trình tại dòng trên cùng, nội dung toàn bộ tệp p3.py như sau:

#!/usr/bin/env python

print ( 'Hello, World' )

Sau đó chuyển chế độ file trở thành thực hiện được:

chmod u+x p3.py

Bây giờ có thể chạy chương trình như sau:

./p3.py

2. In dãy fibonacci

# fibonacci

print ( 'fibonacci:', end = ' ' )
a, b = 0, 1
while b < 10:
    print(b, end = ' ')
    a, b = b, a + b
print()

Đoạn mã trên sẽ in ra phần đầu của dãy fibonacci gồm các số nhỏ hơn 10:

fibonacci: 1 1 2 3 5 8

3. Kiểu xâu kí tự và kiểu bytes

s = 'abcd'

s là một biến xâu kí tự, có chiều dài là 4, phần tử s[1] là kí tự 'b'

print ( len (s) )

print ( s[1] )

Kết quả là:

4

b

s[:] là toàn bộ xâu, s[1:3] là 'bc', s[:3] là 'abc', s[2:] là 'cd', và s[1:-2] là 'b'

\ có thể được sử dụng để thoát dấu ngoặc kép (", double quotes) và dấu nháy đơn (', single quotes). Ví dụ

print ( "\"Yes,\" he said." )

sẽ in ra

"Yes," he said.

Một xâu kí tự có thể trở thành xâu thô bởi thêm r vào trước dấu nháy đầu tiên, khi đó \ nếu có sẽ trở thành kí tự thường

print ( r'C:\some\name' )

Kết quả là

C:\some\name

Tất nhiên có thể sử dụng cách thông thường

print ( 'C:\some\\name' )

Kiểu bytes có thể chứa dữ liệu unicode, khi giải mã sẽ trả về một xâu kí tự, mặc định sử dụng mã hóa utf-8

b = b'\xc3\xa2'

print( b.decode() )

b chứa dữ liệu utf-8 của kí tự 'â' , lệnh print( b.decode() ) in ra kí tự này:

â

Ngược lại,

s = 'â'

b = s.encode()

print ( b )

xâu kí tự s khi mã hóa sẽ cho một dữ liệu kiểu bytes, mặc định chứa dữ liệu utf-8 của nó:

b'\xc3\xa2'

Kiểu xâu kí tự và kiểu bytes không thay đổi được nội dung (chỉ đọc), nhưng kiểu mảng byte thì có thể

b = bytearray( [ 0xc3, 0xa2 ] )

print ( b.decode() )

b[0] = 97

b[1] = 65

print ( b )

Kết quả là

â
bytearray(b'aA')

Để kết xuất một đoạn văn, bạn sử dụng như sau

print(
"""
Hello,
How are you?
"""
)

Lệnh đó tương đương với

print(
"\
\nHello,\n\
How are you?\n\
"
)

Lớp str trả về phiên bản xâu kí tự của đối tượng tham số, ví dụ

s = str(123)

print ( s[:] )

b = bytes( [97] )

s = str(b, 'ascii')

print ( s )

Kết quả:

123

a

Phương thức lower thường xuyên được sử dụng trong lập trình Web, ví dụ để lấy một slug.

print ( 'Page'.lower() )

Kết quả:

page

Phương thức join trả về một xâu (kí tự) ghép các phần tử trong một đối tượng có thể lặp (chúng ta sẽ xem xét đối tượng có thể lặp sau này), ngăn cách bởi xâu gọi phương thức

abc = [ '12', '34', '56' ]
g = '/'
print ( g.join(abc) )

def concat(*args, sep='.'):
    return sep.join(args)

print ( concat( 'omarine', 'omarine', 'org' ) )

Kết quả:

12/34/56

omarine.omarine.org

Phương thức rjust(width[, fillchar]) trả về một xâu được chỉnh phải trong một xâu có chiều dài width. Phần thừa được điền với fillchar (mặc định là kí tự trống). Xâu gốc s sẽ được trả về nếu width nhỏ hơn hoặc bằng len(s).

for x in range(1, 11):
    print(repr(x).rjust(2), repr(x**2).rjust(3), repr(x**3).rjust(4))

Hàm repr trả về một xâu chứa dạng in được của đối tượng tham số.

Kết quả:

 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000

Lệnh trên tương đương với

for x in range(1, 11):
    print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x))

cũng đương tương với

for x in range(1, 11):
    print( '%2d %3d %4d' % ( x, x*x, x*x*x ) )

Kết quả giống như thế nếu chúng ta sử dụng

for x in range(1, 11):
    print( '%2r %3r %4r' % ( x, x*x, x*x*x ) )

Phương thức split(sep=None, maxsplit=-1) được sử dụng thường xuyên trong lập trình Web, chẳng hạn để phân tích cú pháp các thẻ trong trang khuôn mẫu. Phương thức trả về một danh sách các từ trong xâu, sử dụng sep để chia tách. Nếu maxsplit được chỉ ra, thì chỉ có nhiều nhất maxsplit khoảng chia được thực hiện. Như thế danh sách kết quả chỉ có nhiều nhất maxsplit+1 phần tử. Nếu maxsplit không được chỉ ra thì không giới hạn khoảng chia.

Nếu sep có mặt trong tham số, các dấu tách liền nhau không được gộp lại, mà coi như tách lấy xâu rỗng. Ví dụ

li = 'a,,b'.split(',')

print ( li )

cho kết quả

['a', '', 'b']

sep có thể gồm nhiều kí tự, ví dụ

'1<>2<>3'.split('<>')

trả về

['1', '2', '3']

Chia một xâu rỗng với một sep cụ thể sẽ trả về

[ '' ]

Nhưng chia một xâu rỗng không có sep hoặc sep là None sẽ trả về một danh sách rỗng [ ].

print ( '1,2,3'.split(',', maxsplit=1) )

Kết quả:

['1', '2,3']

Nếu sep không được chỉ ra hoặc là None, các khoảng trống liên tiếp được coi như một dấu tách đơn. Các kí tự trống ở đầu và cuối xâu gốc không được tính.

'    1   2   3     '.split()

trả về

['1', '2', '3']

Python không có kiểu kí tự như C/C++. 'a' đơn giản là một xâu có chiều dài là 1.

page = 'Rain, rain, go away', \
       'Come again another day'

unique_words = set(word.replace(',','') for line in page \
    for word in line.lower().split())

print ( unique_words )

Kết quả:

{'again', 'rain', 'come', 'away', 'go', 'another', 'day'}

Phương thức rpartition(sep) cũng được dùng nhiều trong lập trình Web, ví dụ lấy phần cuối của không gian tên của một module làm nhãn để truy cập model của app trong khi xử lý cơ sở dữ liệu. Phương thức này chia xâu gốc tại sep cuối cùng, trả về một tuple 3 phần tử, bao gồm phần trước sep, bản thân sep và phần sau sep. Nếu sep không được tìm thấy, trả về một tuple 3 phần tử bao gồm hai xâu rỗng theo sau bởi chính xâu gốc.

app_name = 'pack.sub.name'

label = app_name.rpartition(".")[2]

print ( label )

Kết quả là

name

4. Kiểu danh sách

Kiểu danh sách và kiểu từ điển được sử dụng thường xuyên trong lập trình Web. Cùng là kiểu dữ liệu tuần tự như xâu kí tự, danh sách hỗ trợ truy cập phần tử theo chỉ số và cắt lát (slice).

#list

li = [1, 3, 5, 7]

li[3] = 8

li.append(9)

li += [11, 13, 15]

print ( li )

li[:] = []

print ( li )

li = [[1, 2, 4], [3, 5, 7]]

print ( li[1][2] )

print ( 'len(li):', len(li) )

Đầu tiên li được gán một danh sách 4 phần tử. Sau đó phần tử thứ tư được gán giá trị 8 thay cho 7. li được thêm một phần tử có giá trị là 9, rồi cộng thêm một danh sách 3 phần tử. Phép gán li[:] = [] làm li trở thành rỗng. Danh sách có thể có các phần tử cũng là danh sách. Lệnh print ( li[1][2] ) in ra phần tử thứ 3 của phần tử danh sách thứ 2, là số 7. Cuối cùng, chiều dài của li là 2, vì nó có 2 phần tử danh sách.

Kết quả chạy đoạn mã trên như sau:

[1, 3, 5, 8, 9, 11, 13, 15]
[]
7
len(li): 2

Nhiều biến có thể được gán từ một danh sách có số phần tử bằng số biến, ví dụ

li = [1, 3, 5, 7]

a, b, c, d = li

print ( c )

Kết quả là

5

Một danh sách có thể được khởi tạo sử dụng lớp list

li = list ( i for i in range (1, 6) )

print ( li )

li = list ( 'abcd' )

print ( li )

Kết quả:

[1, 2, 3, 4, 5]

['a', 'b', 'c', 'd']

5. Danh sách hoạt động như ngăn xếp

stack = [1, 2]

stack2 = [3, 4]

stack.extend(stack2)

print(stack)

stack.append(5)

print(stack)

stack.pop()

print(stack)

Kết quả chạy đoạn mã trên như sau:

[1, 2, 3, 4]

[1, 2, 3, 4, 5]

[1, 2, 3, 4]

Ngoài ra, gọi pop(n) sẽ loại bỏ phần tử có chỉ số n trong danh sách. Phương thức remove(v) loại bỏ phần tử đầu tiên có giá trị v trong danh sách.

stack.remove(3)

print(stack)

stack.pop(1)

print(stack)

Kết quả là

[1, 2, 4]

[1, 4]

6. Danh sách hoạt động như hàng đợi

Để thi hành hàng đợi, sử dụng danh sách với collections.deque.

from collections import deque

queue = deque( [ 1, 2, 3, 4, ] )

print(*queue)

queue.append(5)

print(*queue)

queue.popleft()

print(*queue)

Kết quả như sau:

1 2 3 4

1 2 3 4 5

2 3 4 5

Bạn có nhận thấy dấu phẩy (,) đằng sau phần tử cuối cùng của danh sách? Không hề gì! Python mạnh về xử lý văn bản, nó hiểu dấu phẩy đó khi phân tích cú pháp. Việc cho phép dấu phẩy như thế có lợi khi chúng ta soạn thảo mã nguồn, thêm các phần tử của danh sách không phải bổ sung dấu phẩy, hoặc bớt đi phần tử không phải xóa dấu phẩy. Bạn sẽ thấy điều đó khi soạn thảo các phần tử có tên dài, thường đặt mỗi phần tử trên một dòng. Ví dụ

INSTALLED_APPS = [
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.sites',
        'django.contrib.messages',
        'django.contrib.admin',
        'django.contrib.flatpages',
        'django.contrib.staticfiles',
        'django_extensions',
        'debug_toolbar',
        'paypal',
        'widget_tweaks',
]

7. Kiểu tuple và range

Hai kiểu này cùng thuộc dạng tuần tự như danh sách nhưng không thay đổi được nội dung. Một ví dụ về tuple là tup = 1, 2, 3. Ngoặc đơn là tùy chọn trừ khi nó là một tuple rỗng: tup = ( ).

Kiểu range có 2 dạng:

range(stop)

range(start, stop[, step])

Lệnh print ( *range ( 10 ) ) sẽ cho kết quả

0 1 2 3 4 5 6 7 8 9

Chúng ta xét trường hợp khác:

ran = range ( 10, 0, -1 )

print ( *ran )

Kết quả là

10 9 8 7 6 5 4 3 2 1

8. Kiểu tập hợp

Tập hợp gồm các phần tử khác nhau không phân biệt thứ tự. set('abca') là tập

{ 'a', 'b', 'c' }, cũng bằng với { 'a', 'c', 'b' }.

Tập rỗng được kí kiệu set( ), không sử dụng {}. Kí kiệu đó dành cho từ điển rỗng.

a = set('abca')

print ( a )

b = { 'b', 'c', 'd' }

print( a | b )

print( a & b )

print( a – b )

print( a ^ b )

print ( a – a )

Kết quả:

{'a', 'b', 'c'}

{'b', 'c', 'd', 'a'}

{'b', 'c'}

{'a'}

{'d', 'a'}

set()

9. Định nghĩa hàm và đóng gói

Chúng ta tạo thư mục fibo và 2 file trong đó như sau:

mkdir fibo
touch fibo/fibo.py
cat > fibo/__init__.py << EOF
from fibo.fibo import fib
EOF

Sau đó soạn thảo tệp fibo.py có nội dung sau:

def fib(n):
    result = []
    a, b = 0, 1
    while b < n:
        result.append(b)
        a, b = b, a + b
    return result

if __name__ == "__main__":
    import sys
    print ( fib(int(sys.argv[1])) )

Những thao tác trên đã tạo ra gói fibo, gói như thế có thể được chạy với tham số dòng lệnh:

python fibo/fibo.py 10

Kết quả là:

[1, 1, 2, 3, 5, 8]

Để sử dụng gói trong chương trình khác, bạn nhập khẩu gói và gọi hàm fib:

from fibo import fib

print ( fib(100) )

Hàm dir cho biết các tên trong một module, bao gồm tên biến, hàm và module, nhưng không liệt kê các tên biến và hàm built-in. Chúng ở trong module chuẩn builtins

10. So sánh

print('abc' < 'abcd')
print('(1, 2, 3) < (1, 2, 4):', (1, 2, 3) < (1, 2, 4))
print('(1, 2, 3) == (1.0, 2.0, 3.0):', (1, 2, 3) == (1.0, 2.0, 3.0))
if [1, 2, 3 ] < [ 1, 2, 4 ]:
    print ( 'yes' )
else:
    print ( 'no' )

Kết quả:

True
(1, 2, 3) < (1, 2, 4): True
(1, 2, 3) == (1.0, 2.0, 3.0): True
yes

Bạn đón đọc phần tiếp theo trong bài sau.

Advertisements

Gửi phản hồi

Website này sử dụng Akismet để hạn chế spam. Tìm hiểu bình luận của bạn được duyệt như thế nào.

%d bloggers like this: