Ngân hàng câu hỏi của chương

Câu hỏi: PRP201c - Phần 2: Cấu trúc dữ liệu và xử lý văn bản

41 câu trắc nghiệm kèm lời giải của môn PRP201c - Lập trình Python, xếp theo thứ tự nhập vào ngân hàng. Trang 2/3 — câu 21–40.

Danh sách câu hỏi

40/41 câuCòn 1
A{}
B()
C[]
DNone
Lời giải

Đáp án đúng: "[]". Cặp ngoặc vuông rỗng tạo một list (danh sách) rỗng, ví dụ friends = [], sau đó có thể thêm phần tử bằng friends.append('Joe'); cách viết tương đương là gọi hàm list(). Phương án "{}" tạo một dict (từ điển) rỗng chứ không phải list, và cũng không phải set rỗng, vì set rỗng phải viết set(). Phương án "()" tạo một tuple rỗng; tuple giống list ở chỗ giữ thứ tự phần tử nhưng là kiểu bất biến (immutable), không append được. Phương án "None" là giá trị đặc biệt biểu thị không có giá trị, thuộc kiểu NoneType; biến bằng None không phải list và gọi append trên nó sẽ ném AttributeError. Có thể tự kiểm bằng type([]), kết quả là lớp list.

Mở trang câu hỏi này →
ASyntaxError
BIndexError
CFileNotFoundError
DNameError
Lời giải
Đáp án đúng: "FileNotFoundError". Khi mở tệp bằng open('ten.txt') mà tệp không tồn tại, Python 3 phát sinh FileNotFoundError, một lớp con của OSError; đây là lỗi lúc chạy (runtime) điển hình mà ta bọc lời gọi open trong try/except để báo cho người dùng và thoát gọn thay vì để chương trình đổ traceback. "SyntaxError" sai vì lỗi cú pháp phát hiện khi biên dịch, trước khi khối try kịp chạy, nên không bắt được bằng try/except trong cùng tệp. "IndexError" sai vì nó phát sinh khi truy cập chỉ số vượt ngoài danh sách hoặc chuỗi, không gắn với việc mở tệp. "NameError" sai vì nó báo dùng tên biến chưa định nghĩa; bắt nó cũng được nhưng đó là lỗi lập trình, không phải lỗi đặc trưng khi làm việc với tệp.
Mở trang câu hỏi này →
A[123, 'john', 123, 'john']
B[123, 'john'] * 2
CError
DNone of the others
Lời giải
Đáp án đúng: "[123, 'john', 123, 'john']". Toán tử nhân giữa một list và một số nguyên n tạo ra list mới bằng cách nối list đó với chính nó n lần (phép lặp, repetition), không nhân từng phần tử như mảng NumPy, nên tinylist nhân 2 cho list bốn phần tử như trên. Cách viết print không ngoặc là của Python 2; ở Python 3 viết print(tinylist * 2) cho cùng kết quả. "[123, 'john'] * 2" là biểu thức chứ không phải kết quả: print tính giá trị trước rồi in giá trị đó, không in lại nguyên văn biểu thức. "Error" sai vì list hỗ trợ nhân với số nguyên; TypeError chỉ xảy ra khi nhân list với list hoặc với số thực. "None of the others" sai vì đã có một kết quả khớp đúng với cách Python tính. Tương tự, chuỗi cũng lặp được: 'ab' * 3 cho 'ababab'.
Mở trang câu hỏi này →
Afruit[5]
Bfruit[-1]
Cfruit[6]
Dfruit[-2]
Lời giải
Đáp án đúng: "fruit[6]". Chuỗi banana dài 6 ký tự, chỉ số dương chạy từ 0 đến 5 (b, a, n, a, n, a), còn chỉ số âm chạy từ -1 đến -6, đếm ngược từ cuối. Truy cập một chỉ số nằm ngoài khoảng đó gây IndexError: string index out of range. fruit[6] vượt chỉ số lớn nhất là 5 nên lỗi; đây là lỗi kinh điển khi quên rằng chỉ số bắt đầu từ 0, tức vị trí cuối là len(fruit) - 1. "fruit[5]" hợp lệ, trả về 'a' là ký tự cuối. "fruit[-1]" hợp lệ, cũng là ký tự cuối 'a', vì -1 nghĩa là vị trí cuối cùng. "fruit[-2]" hợp lệ, trả về 'n' là ký tự áp chót. Ba cách viết này đều lấy được một ký tự có thật nên không gây lỗi.
Mở trang câu hỏi này →
AHello World
B'Hello World'
C'Hello\nWorld'
D'Hello/nWorld'
Lời giải
Đáp án đúng: "'Hello\nWorld'". Hàm repr() trả về chuỗi biểu diễn chính thức (representation) của đối tượng, tức dạng có thể gõ lại thành mã Python: với chuỗi, kết quả có cặp nháy đơn bao quanh và các ký tự đặc biệt được viết dưới dạng thoát. Chuỗi trong câu chứa một ký tự xuống dòng thật, nhưng repr hiện nó thành hai ký tự gạch ngược và n, nên kết quả nằm gọn trên một dòng kèm dấu nháy. Vì thế repr rất hữu ích khi gỡ lỗi khoảng trắng ẩn. "Hello World" không đúng: ngay cả print cũng không cho ra dòng này, vì print in Hello và World trên hai dòng chứ không thay bằng dấu cách, còn repr thì giữ cả dấu nháy lẫn chuỗi thoát. "'Hello World'" sai vì repr không thay ký tự xuống dòng bằng dấu cách. "'Hello/nWorld'" sai vì dấu thoát dùng gạch ngược chứ không phải gạch xuôi; gạch xuôi đi với n chỉ là hai ký tự bình thường.
Mở trang câu hỏi này →
Đề bài
d = dict()
for c in word:
    d[c] = d.get(c, 0) + 1
print(d)
A{'b': 1, 'r': 2, 'o': 2, 'n': 2, 't': 1, 's': 1, 'a': 2, 'u': 1}
B{'b': 1, 'r': 1, 'o': 2, 'n': 2, 't': 1, 's': 1, 'a': 2, 'u': 2}
C{'b': 1, 'r': 1, 'o': 2, 'n': 2, 't': 1, 's': 1, 'a': 2, 'u': 1}
D{'b': 1, 'r': 1, 'o': 1, 'n': 1, 't': 1, 's': 1, 'a': 1, 'u': 1}
Lời giải
Đáp án đúng: "{'b': 1, 'r': 2, 'o': 2, 'n': 2, 't': 1, 's': 1, 'a': 2, 'u': 1}". Mã duyệt từng chữ của brontosaurus và đếm bằng d.get(c, 0) + 1, từ điển giữ thứ tự chèn nên kết quả thật là {'b': 1, 'r': 2, 'o': 2, 'n': 1, 't': 1, 's': 2, 'a': 1, 'u': 2}; nói thẳng là đề này không có phương án nào khớp hoàn toàn. Phương án được chọn đúng b, t, r, o, tổng các số đếm bằng 12 đúng số chữ của từ, nhưng sai bốn khoá n (thật là 1), s (thật là 2), a (thật là 1) và u (thật là 2). "{'b': 1, 'r': 1, 'o': 2, 'n': 2, 't': 1, 's': 1, 'a': 2, 'u': 2}" cũng có tổng 12 và cũng sai đúng bốn khoá (r chỉ đếm 1 lần dù xuất hiện hai lần, cùng n, s, a), nên về mức độ sai hai phương án này ngang nhau; đề không in khoá, đáp án chốt ở đây chỉ là quy ước ưu tiên phương án đếm đúng hai chữ lặp đầu tiên. "{'b': 1, 'r': 1, 'o': 2, 'n': 2, 't': 1, 's': 1, 'a': 2, 'u': 1}" sai vì tổng chỉ 11, thiếu một chữ, và sai r, n, s, a. "{'b': 1, 'r': 1, 'o': 1, 'n': 1, 't': 1, 's': 1, 'a': 1, 'u': 1}" sai vì gán mọi chữ bằng 1 như thể không cộng dồn, tổng chỉ 8.
Mở trang câu hỏi này →
A(1,1,2,2,3,3)
B[1,1,2,2,3,3]
CIllegal
D(1,2,3,1,2,3)
Lời giải
Đáp án đúng: "Illegal". Toán tử * với một số nguyên chỉ được định nghĩa cho các kiểu dãy (sequence) như list, tuple, str: [1, 2] * 2 cho [1, 2, 1, 2]. Set là tập hợp không có thứ tự và không chứa phần tử trùng, nên việc nhân bản phần tử là vô nghĩa và Python không định nghĩa phép này; 2 * s1 ném TypeError: unsupported operand type(s) for *: 'int' and 'set'. "(1,1,2,2,3,3)" sai về cả hai mặt: phép nhân dãy nối nguyên bản sao chứ không lặp từng phần tử, và kết quả không thể là tuple khi đầu vào là set. "[1,1,2,2,3,3]" cũng không xảy ra, kể cả với list thì 2 * [1,2,3] cho [1,2,3,1,2,3]. "(1,2,3,1,2,3)" đúng là kết quả của 2 * (1,2,3) khi dùng tuple, nhưng s1 là set nên không áp dụng được.
Mở trang câu hỏi này →
28What will the following Python code print out?4 lựa chọncó code
Đề bài
friends = [ 'Joseph', 'Glenn', 'Sally' ]
friends.sort()
print (friends[1])
AGlenn
BJoseph
CSally
DFriends
Lời giải
Đáp án đúng: "Joseph". Phương thức sort() sắp xếp danh sách tại chỗ (in-place) theo thứ tự từ điển của chuỗi, nên friends trở thành ['Glenn', 'Joseph', 'Sally'] vì G đứng trước J, J đứng trước S. Chỉ số trong Python bắt đầu từ 0, nên friends[1] là phần tử thứ hai, tức Joseph. "Glenn" sai vì đó là friends[0], phần tử đầu tiên sau khi sắp; chọn nó là nhầm chỉ số bắt đầu từ 1. "Sally" sai vì đó là friends[2]. Nếu không gọi sort() thì friends[1] lại là Glenn, nên điểm mấu chốt là sort() đã đổi thứ tự danh sách gốc. "Friends" sai vì print in giá trị phần tử chứ không in tên biến, và tên biến cũng viết thường là friends.
Mở trang câu hỏi này →
Aprint(length(data))
Bprint(data.length())
Cprint(len(data))
Dprint(data.length)
Lời giải
Đáp án đúng: "print(len(data))". len() là hàm dựng sẵn trả về số phần tử của một đối tượng có độ dài như chuỗi, list, tuple hay dictionary; Python viết len(obj) chứ không gọi qua phương thức, bên trong nó gọi phương thức đặc biệt __len__ của đối tượng, rồi print in con số đó ra màn hình. "print(length(data))" sai vì Python không có hàm dựng sẵn tên length, chạy sẽ báo NameError. "print(data.length())" sai vì list không có phương thức length; cách viết này giống phương thức của một số ngôn ngữ khác, trong Python sẽ báo AttributeError. "print(data.length)" là kiểu thuộc tính độ dài của mảng JavaScript; list Python không có thuộc tính này nên cũng báo AttributeError. Ghi nhớ: trong Python, độ dài luôn lấy bằng hàm len().
Mở trang câu hỏi này →
AIt indicates the end of one line of text and the beginning of another line of text
BIt adds a new network connection to retrieve files from the network
CIt allows us to open more than one files and read them in a synchronized manner
DIt enables random movement throughout the file
Lời giải
Đáp án đúng: "It indicates the end of one line of text and the beginning of another line of text". Tệp văn bản thực chất là một chuỗi ký tự dài; ký tự xuống dòng (newline), trong Python viết là \n, là ký tự đặc biệt đánh dấu chỗ một dòng kết thúc và dòng kế tiếp bắt đầu, nhờ đó trình soạn thảo hiển thị được nhiều dòng và vòng lặp for line in fhand tách được từng dòng. len('X\nY') bằng 3 vì \n chỉ tính là một ký tự. Phương án "It adds a new network connection to retrieve files from the network" sai vì kết nối mạng do socket hoặc urllib đảm nhận, một ký tự trong tệp không làm được việc đó. Phương án "It allows us to open more than one files and read them in a synchronized manner" sai vì mở nhiều tệp là việc gọi open() nhiều lần, không liên quan tới ký tự xuống dòng. Phương án "It enables random movement throughout the file" sai vì di chuyển tuỳ ý trong tệp là việc của phương thức seek(), còn newline chỉ phân tách các dòng.
Mở trang câu hỏi này →
31What is 'abc'[1]?4 lựa chọn
Aa
Bb
Cc
DError
Lời giải
Đáp án đúng: "b". Chuỗi trong Python là dãy ký tự, truy cập bằng chỉ số đặt trong ngoặc vuông và chỉ số bắt đầu từ 0. Với 'abc', vị trí 0 là a, vị trí 1 là b, vị trí 2 là c, nên 'abc'[1] trả về 'b', ký tự thứ hai chứ không phải thứ nhất. "a" là kết quả của 'abc'[0], đáp án của người quen đếm từ 1 như đời thường. "c" là kết quả của 'abc'[2] hoặc 'abc'[-1], tức ký tự cuối. "Error" chỉ xảy ra khi chỉ số vượt khỏi khoảng hợp lệ, như 'abc'[3] gây IndexError; chỉ số 1 nằm trong khoảng từ 0 đến 2 nên hợp lệ. Đặt chỉ số ngay sau một hằng chuỗi là hoàn toàn được phép, giống như đặt sau tên biến.
Mở trang câu hỏi này →
Areplace()
BreplaceString()
Crepl()
Drep()
Lời giải

Đáp án đúng: "replace()". Kiểu str của Python có phương thức replace(old, new) trả về chuỗi mới, trong đó mọi lần xuất hiện của chuỗi con old được thay bằng new; ví dụ 'banana'.replace('a', 'o') cho 'bonono'. Chuỗi là bất biến (immutable) nên phương thức không sửa chuỗi gốc, phải gán kết quả cho biến nếu muốn dùng tiếp. "replaceString()" không tồn tại trong str; đó là kiểu đặt tên của một số ngôn ngữ khác, gọi trong Python sẽ báo AttributeError. "repl()" cũng không phải phương thức chuỗi; REPL là tên gọi vòng đọc, thực thi, in của chế độ tương tác, còn thay thế theo mẫu biểu thức chính quy thì dùng re.sub. "rep()" không tồn tại; dễ nhầm với repr(), hàm dựng sẵn trả về chuỗi biểu diễn của một đối tượng, không liên quan đến việc thay thế.

Mở trang câu hỏi này →
ALine merges with next
BFile is deleted
CData is lost
DNothing special
Lời giải
Đáp án đúng: "Line merges with next". Phương thức write() ghi đúng những gì được truyền vào, không tự thêm ký tự xuống dòng như print; vì vậy nếu gọi write hai lần với hai chuỗi mà không tự thêm ký tự xuống dòng vào cuối chuỗi thứ nhất, hai chuỗi sẽ nằm liền nhau trên cùng một dòng trong tệp. "File is deleted" sai vì thiếu ký tự xuống dòng không làm mất tệp; tệp chỉ bị làm rỗng khi mở lại bằng chế độ 'w'. "Data is lost" sai vì mọi ký tự vẫn được ghi đầy đủ, chỉ là dính liền nhau, không mất byte nào. "Nothing special" sai vì có hậu quả thực tế: khi đọc lại bằng vòng lặp for line in f, những đoạn định ghi thành nhiều dòng riêng sẽ chỉ trả về một dòng duy nhất, làm sai việc đếm hay xử lý theo dòng.
Mở trang câu hỏi này →
Ab
Ba
Cn
DIndexError
Lời giải
Đáp án đúng: "a". Chuỗi trong Python hỗ trợ chỉ số âm (negative index) đếm từ cuối: fruit[-1] là ký tự cuối cùng, fruit[-2] là ký tự áp cuối, và cứ thế. Chuỗi banana gồm sáu ký tự b, a, n, a, n, a ở các chỉ số 0 tới 5, nên fruit[-1] tương đương fruit[len(fruit) - 1], tức fruit[5], là chữ a cuối chuỗi. Phương án "b" là ký tự đầu tiên, lấy bằng fruit[0] hoặc fruit[-6]. Phương án "n" là ký tự ở fruit[-2] hoặc fruit[4], áp cuối chứ không phải cuối. Phương án "IndexError" sai vì -1 luôn là chỉ số hợp lệ với một chuỗi không rỗng; IndexError chỉ xảy ra khi chỉ số vượt ra ngoài độ dài, như fruit[6] hoặc fruit[-7].
Mở trang câu hỏi này →
AUsing a dictionary with characters as keys and counters as values
BUsing a list with 26 elements, one for each letter of the alphabet
CUsing a set to store characters
DUsing 26 variables, one for each letter of the alphabet
Lời giải
Đáp án đúng: "Using a set to store characters". Đếm tần suất ký tự nghĩa là với mỗi ký tự phải nhớ nó xuất hiện bao nhiêu lần. Set (tập hợp) chỉ lưu mỗi phần tử một lần và không gắn kèm con số nào, nên thêm 'a' lần thứ hai cũng không thay đổi gì; set chỉ cho biết những ký tự nào có mặt chứ không cho biết số lần, vì vậy đây là cách KHÔNG đếm được. "Using a dictionary with characters as keys and counters as values" đếm được và là cách gọn nhất, như counts[c] = counts.get(c, 0) + 1. "Using a list with 26 elements, one for each letter of the alphabet" cũng đếm được: đổi chữ cái thành vị trí bằng ord(c) - ord('a') rồi tăng phần tử tương ứng. "Using 26 variables, one for each letter of the alphabet" đếm được nhưng rất vụng, cần một chuỗi if dài để chọn biến cần tăng; cách dùng list và cách dùng biến chỉ áp cho 26 chữ cái tiếng Anh, còn dict áp cho mọi ký tự. Ba cách này đều đếm được nên không được chọn ở câu hỏi phủ định.
Mở trang câu hỏi này →
Đề bài
print(
    '$100 $200 $300'.count('$'),
    '$100 $200 $300'.count('$', 5, 10),
    '$100 $200 $300'.count('$', 5)
)
A3 1 2
B3 1 1
C3 2 1
D3 1 0
Lời giải
Đáp án đúng: "3 1 2". Phương thức str.count(sub, start, end) đếm số lần sub xuất hiện trong lát cắt từ start đến trước end. Chuỗi '$100 $200 $300' có ba dấu đô la ở vị trí 0, 5 và 10. Lời gọi thứ nhất không có giới hạn nên đếm cả ba, cho 3. Lời gọi thứ hai xét vị trí 5 đến 9: chỉ có dấu ở vị trí 5, còn vị trí 10 nằm ngoài vì end không được tính, cho 1. Lời gọi thứ ba chỉ có start = 5 nên xét từ 5 đến hết chuỗi, gặp dấu ở 5 và 10, cho 2. print nhận ba đối số và in chúng cách nhau bởi dấu cách. "3 1 1" sai ở giá trị cuối, quên rằng thiếu end thì đếm tới cuối chuỗi nên vị trí 10 được tính. "3 2 1" đổi chỗ hai kết quả sau, như thể lời gọi thứ hai lấy cả vị trí 10 còn lời gọi thứ ba bỏ sót. "3 1 0" coi như lời gọi thứ ba không thấy dấu nào, có lẽ do nhầm start là vị trí kết thúc.
Mở trang câu hỏi này →
A21
B[4, 5, 6]
C15
D6
Lời giải
Đáp án đúng: "6". Dấu cộng giữa hai danh sách là phép nối (concatenation): a + b tạo danh sách mới [1, 2, 3, 4, 5, 6], nên len(c) đếm số phần tử và cho 6. Dòng print len(c) là cú pháp Python 2, nơi print là câu lệnh; trên Python 3 phải viết print(len(c)), còn kết quả vẫn là 6. "21" sai vì đó là tổng các phần tử 1 + 2 + ... + 6, tức sum(c), không phải độ dài. "15" sai vì đó là tổng 4 + 5 + 6 của riêng b, hoặc nhầm phép cộng thành cộng từng giá trị. "[4, 5, 6]" sai vì đó là chính danh sách b; dấu cộng không ghi đè a bằng b, và len trả về một số chứ không trả về danh sách.
Mở trang câu hỏi này →
Astrip()
Blen()
Cptrim()
Dtrim()
Lời giải
Đáp án đúng: "strip()". Phương thức str.strip() trả về bản sao của chuỗi đã bỏ khoảng trắng (whitespace) ở cả đầu lẫn cuối, gồm dấu cách, tab và ký tự xuống dòng; ví dụ ' Hello Bob '.strip() cho 'Hello Bob', còn khoảng trắng ở giữa vẫn giữ nguyên. Hai biến thể của nó là lstrip() chỉ bỏ bên trái và rstrip() chỉ bỏ bên phải. Phương án "len()" là hàm dựng sẵn trả về độ dài chuỗi, không thay đổi nội dung chuỗi. Phương án "ptrim()" không tồn tại trong Python, chỉ là tên bịa gần giống trim. Phương án "trim()" là tên hàm tương ứng trong JavaScript, Java hay PHP; Python không có phương thức trim cho chuỗi, gọi nó sẽ ném AttributeError.
Mở trang câu hỏi này →
Aappend()
BIndex assignment list[2] = x
Cremove()
Dinsert()
Lời giải
Đáp án đúng: "Index assignment list[2] = x". List là kiểu khả biến (mutable), nên có thể ghi đè phần tử tại một vị trí bằng phép gán theo chỉ số: lst[2] = x thay giá trị ở vị trí 2, độ dài list giữ nguyên, các phần tử khác không bị dịch. Chỉ số phải nằm trong khoảng hiện có, nếu không sẽ gây IndexError. "append()" thêm một phần tử mới vào cuối list, làm list dài thêm chứ không sửa phần tử có sẵn. "remove()" xoá lần xuất hiện đầu tiên của một giá trị, tìm theo giá trị chứ không theo vị trí, và làm list ngắn lại. "insert()" chèn phần tử vào một vị trí, như lst.insert(2, x), đẩy các phần tử từ vị trí đó lùi ra sau; giá trị cũ ở vị trí 2 vẫn còn, chỉ bị dời chỗ, nên đó là chèn chứ không phải cập nhật. Lưu ý đặt tên biến là list sẽ che mất hàm list() có sẵn, nên thực tế nên dùng tên khác.
Mở trang câu hỏi này →
At becomes sorted list
Bt becomes None
Ct becomes reversed
DError occurs
Lời giải
Đáp án đúng: "t becomes None". Phương thức sort() của list sắp xếp tại chỗ (in-place), tức sửa trực tiếp list đó, và trả về None; vì vậy khi gán lại vào t, list vẫn được sắp xếp xong nhưng tên t bị gán thành None và mất tham chiếu tới list. Muốn giữ kết quả, hãy gọi t.sort() trên một dòng riêng, hoặc dùng t = sorted(t) vì sorted() trả về list mới. "t becomes sorted list" chỉ đúng nếu dùng sorted(t), không đúng với sort(). "t becomes reversed" sai vì sort() sắp tăng dần chứ không đảo; muốn đảo phải dùng reverse() hoặc sort(reverse=True), mà reverse() cũng trả về None. "Error occurs" sai vì phép gán chạy bình thường; lỗi chỉ xuất hiện về sau khi dùng t như list, ví dụ lấy phần tử đầu sẽ gây TypeError vì NoneType không truy cập theo chỉ số được.
Mở trang câu hỏi này →