Cách tính to hợp trong python

Sau khi đã giải được 20 Bài tập Python cơ bản có lời giải, mời bạn tiếp tục thử sức các bài tập Python chỉ sử dụng vòng lặp và các kiểu dữ liệu cơ bản như kiểu danh sách list, kiểu xâu str.

Show

Bài 1. [Đại học Thái Nguyên 2000] Từ các chữ số 1; 2; 3 có thể lập được bao nhiêu số tự nhiên gồm 5 chữ số có mặt đủ 3 chữ số nói trên?

Đáp số: 150 số.

Hướng dẫn. Đầu tiên sử dụng 5 vòng lặp để tạo một danh sách tất cả các số tự nhiên gồm 5 chữ số được tạo thành từ các chữ số 1, 2, 3. Sau đó duyệt qua tất cả các phần tử của danh sách này và dùng hàm membership in để kiểm tra xem phần tử đó có mặt cả ba chữ số 1, 2, 3 hay không. Nếu có thì tăng biến đếm count, và in phần tử đó ra nếu muốn.

numbers = ['1', '2', '3']
results = []

for a in numbers:
  for b in numbers:
    for c in numbers:
      for d in numbers:
        for e in numbers:
          # results.append([a,b,c,d,e])
          results.append(a+b+c+d+e)

count = 1

for temp in results:
  # print(temp)
  if ('1' in temp) and ('2' in temp) and ('3' in temp):
    print(str(count) +': '+temp)
    count +=1

Bài 2. Có bao nhiêu số tự nhiên gồm 5 chữ số và chia hết cho 7.

Đáp số: 12857 số.

Hướng dẫn. Sử dụng một biến đếm count. Duyệt tất cả các số tự nhiên có 5 chữ số (từ 10000 đến 99999) và kiểm tra xem số đó có chia hết cho 7 hay không. Nếu có thì tăng biến đếm. Có thể in ra số đó nếu muốn.

count = 0
for i in range(10000, 99999 + 1):	
  if (i % 7 == 0):
    count += 1
    print(str(count) + ': ' + str(i))

Bài 3. Một em bé có thể mang họ cha là Nguyễn, hoặc họ mẹ là Lê; tên đệm có thể là Văn, Hữu hoặc Đình; tên có thể là Nhân, Nghĩa, Trí hoặc Dũng. Hỏi có bao nhiêu cách đặt tên cho bé?

Đáp số. Có 24 cách đặt tên.

bien_dem = 1
ho = ['Nguyễn', 'Lê']
dem = ['Văn', 'Hữu', 'Đình']
ten = ['Nhân', 'Nghĩa', 'Trí', 'Dũng']
for h in ho:
  for d in dem:
    for t in ten:
      print(str(bien_dem) + ': ' + h + ' ' + d + ' ' + t)
      bien_dem += 1

Bài 4. [Đại học An Ninh 1997] Từ các chữ số từ 0 đến 6 có thể lập được bao nhiêu số tự nhiên chẵn gồm 3 chữ số khác nhau?

Nếu sử dụng kiểu dữ liệu tập hợp set, chúng ta có thể in trực tiếp ra các số thỏa mãn yêu cầu:

numbers_even = {'0', '2', '4', '6'}
numbers_odd = {'1', '3', '5'}
numbers = numbers_even | numbers_odd

results = []
count = 0

for c in numbers_even:
  for a in (numbers - {'0'}):
    if (a != c):
      for b in numbers:
        if ( b!=a and b!= c):
          count += 1
          print(str(count) + ': ' +a+b+c)

Cách khác, chúng ta không sử dụng kiểu dữ liệu tập hợp thì sẽ in ra rất cả các số tự nhiên chẵn sau đó loại đi các số mà có chữ số giống nhau:

count = 0
results =[]

for a in range(1,7):
  for b in range(0,7):
    for c in {0,2,4,6}:
      results.append(str(a)+str(b)+str(c))

temp = []
for x in results:
  if not((x[0] == x[1]) or (x[0]==x[2]) or (x[1]==x[2])):
    temp.append(x)
print(len(temp))
print(temp)

Bài 5. Từ các chữ số 0,1,2,3,4,5,6 có thể lập được bao nhiêu số tự nhiên gồm 3 chữ số khác nhau và phải có mặt chữ số 5?

Đáp số: 80 số.

count = 0
results =[]

for a in range(1,7):
  for b in range(0,7):
    for c in range(0,7):
      results.append(str(a)+str(b)+str(c))

temp = []
for x in results:
  if not((x[0] == x[1]) or (x[0]==x[2]) or (x[1]==x[2])) and ('5' in x):
    temp.append(x)
print(len(temp))
print(temp)

Bài viết gốc: https://manhhomienbienthuy.github.io/2017/07/24/mot-vai-trick-python-ban-nhat-dinh-phai-biet-tren-con-duong-go-pro.html (đã xin phép tác giả

Cách tính to hợp trong python
)

Với bất kỳ ngôn ngữ nào, nếu bạn muốn thuần thục ngôn ngữ đó, bạn nhất định phải biết các thủ thuật cũng như tính năng đặc trưng của ngôn ngữ đó. Những điều này thường được tích lũy qua quá trình làm việc lâu dài, mà một vài quyển sách dạy lập trình không thể nói hết được. Python cũng không phải là ngoại lệ.

Bài viết này sẽ trình bày một vài thủ thuật trong số đó. Các thủ thuật này sẽ giúp code của bạn trong "pro" hơn, ngắn gọn và dễ hiểu hơn. Nếu bạn đã có kinh nghiệm với Python, có thể bạn đã biết gần hết các thủ thuật, nhưng vẫn có thể có những thứ bạn chưa đụng đến bao giờ. Còn nếu bạn mới làm quen với ngôn ngữ, bài viết này sẽ giúp ích cho bạn rất nhiều.

Mỗi một thủ thuật hoặc tính năng của ngôn ngữ đều được demo bằng code và tôi nghĩ rằng, mình không cần phải nói thêm gì nữa. Mọi thứ để đã được thể hiện ở code rồi.

Trong bài viết này, tôi sẽ sử dụng Python 3, code Python 2 có thể thay đổi đôi chút.

Unpack

>>> a, b, c = 1, 2, 3
>>> a, b, c
(1, 2, 3)
>>> a
1
>>> b
2
>>> c
3
>>> a, b, c = (2 * i + 1 for i in range(3))
>>> a, b, c
(1, 3, 5)
>>> a, (b, c), d = (1, (2, 3), 4)
>>> a, b, c, d
(1, 2, 3, 4)

Swap hai biến

>>> a, b = 1, 2
>>> a, b = b, a
>>> a, b
(2, 1)

Sử dụng toán tử * đại diện cho "phần còn lại"

>>> a, *b, c = [1, 2, 3, 4, 5]
>>> a
1
>>> b
[2, 3, 4]
>>> c
5

Index âm

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> a[-1]
10
>>> a[-3]
8

Slice

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> a[2:8]
[2, 3, 4, 5, 6, 7]

Slice với index âm

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> a[-4:-2]
[7, 8]

Slice nhảy bước

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> a[::2]
[0, 2, 4, 6, 8, 10]
>>> a[::3]
[0, 3, 6, 9]
>>> a[2:8:2]
[2, 4, 6]

Slice nhảy bước âm

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> a[::-1]
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> a[::-2]
[10, 8, 6, 4, 2, 0]

Slice kết hợp gán với list

>>> a = [1, 2, 3, 4, 5]
>>> a[2:3] = [0, 0]
>>> a
[1, 2, 0, 0, 4, 5]
>>> a[1:1] = [8, 9]
>>> a
[1, 8, 9, 2, 0, 0, 4, 5]
>>> a[1:-1] = []
>>> a
[1, 5]

Slice đặt tên

>>> a = [0, 1, 2, 3, 4, 5]
>>> LASTTHREE = slice(-3, None)
>>> LASTTHREE
slice(-3, None, None)
>>> a[LASTTHREE]
[3, 4, 5]
a = [0, 1]
>>> a[LASTTHREE]
[0, 1]

Duyệt iterable

Dùng enumerate duyệt qua cả index và giá trị

>>> a = ['Hello', 'world', '!']
>>> for i, x in enumerate(a):
...     print('{}: {}'.format(i, x))
...
0: Hello
1: world
2: !

Duyệt qua key và value của dict

>>> m = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
>>> for k, v in m.items():
...     print('{}: {}'.format(k, v))
...
b: 2
c: 3
a: 1
d: 4

Zip và ứng dụng

>>> a = [1, 2, 3]
>>> b = ['a', 'b', 'c']
>>> z = list(zip(a, b))
>>> z
[(1, 'a'), (2, 'b'), (3, 'c')]
>>> list(zip(*z))
[(1, 2, 3), ('a', 'b', 'c')]

Nhóm các phần tử liền nhau

Dùng itertools

>>> a = [1, 2, 3, 4, 5, 6]
>>> group_adjacent = lambda a, k: list(zip(*([iter(a)] * k)))
>>> group_adjacent(a, 3)
[(1, 2, 3), (4, 5, 6)]
>>> group_adjacent(a, 2)
[(1, 2), (3, 4), (5, 6)]
>>> group_adjacent(a, 1)
[(1,), (2,), (3,), (4,), (5,), (6,)]

Dùng slice

>>> from itertools import islice
>>> a = [1, 2, 3, 4, 5, 6]
>>> group_adjacent = lambda a, k: list(zip(*(islice(a, i, None, k) for i in range(k))))
>>> group_adjacent(a, 3)
[(1, 2, 3), (4, 5, 6)]
>>> group_adjacent(a, 2)
[(1, 2), (3, 4), (5, 6)]
>>> group_adjacent(a, 1)
[(1,), (2,), (3,), (4,), (5,), (6,)]

Chuyển đổi dict

>>> m = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
>>> m.items()
dict_items([('b', 2), ('c', 3), ('a', 1), ('d', 4)])
>>> list(zip(m.values(), m.keys()))
[(2, 'b'), (3, 'c'), (1, 'a'), (4, 'd')]
>>> mi = dict(zip(m.values(), m.keys()))
>>> mi
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}

Làm phẳng list

Dùng itertools

>>> import itertools
>>> a = [[1, 2], [3, 4], [5, 6]]
>>> list(itertools.chain.from_iterable(a))
[1, 2, 3, 4, 5, 6]

Dùng sum

>>> a = [[1, 2], [3, 4], [5, 6]]
>>> sum(a, [])
[1, 2, 3, 4, 5, 6]

Dùng list comprehension

>>> a = [[1, 2], [3, 4], [5, 6]]
>>> [x for l in a for x in l]
[1, 2, 3, 4, 5, 6]
>>> a = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
>>> [x for l1 in a for l2 in l1 for x in l2]
[1, 2, 3, 4, 5, 6, 7, 8]

Nâng cao: list với các phần tử bất kỳ

>>> a = [1, 2, [3, 4], [[5, 6], [7, 8]]]
>>> latten = lambda x: [y for l in x for y in flatten(l)] if type(x) is list else [x]
>>> flatten(a)
[1, 2, 3, 4, 5, 6, 7, 8]

Sử dụng comprehensions

Biểu thứ generator

>>> g = (x ** 2 for x in range(10))
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> sum(x ** 3 for x in range(10))
2025
>>> sum(x ** 3 for x in range(10) if x % 3 == 1)
408

Dict comprehension

>>> m = {x: x ** 2 for x in range(5)}
>>> m
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
>>> m = {x: 'A' + str(x) for x in range(10)}
>>> m
{0: 'A0', 1: 'A1', 2: 'A2', 3: 'A3', 4: 'A4', 5: 'A5', 6: 'A6', 7: 'A7', 8: 'A8', 9: 'A9'}

Chuyển đổi dict dùng comprehension

>>> m = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
>>> m
{'b': 2, 'c': 3, 'a': 1, 'd': 4}
>>> {v: k for k, v in m.items()}
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}

Tập hợp và các phép toán liên quan

>>> A = {1, 2, 3, 3}
>>> B = {3, 4, 5, 6, 7}
>>> A | B
{1, 2, 3, 4, 5, 6, 7}
>>> A & B
{3}
>>> A - B
{1, 2}
>>> B - A
{4, 5, 6, 7}
>>> A ^ B
{1, 2, 4, 5, 6, 7}
>>> A ^ B == ((A - B) | (B - A))
True

Sự vi diệu của collections

namedtupple

>>> import collections
>>> Point = collections.namedtuple('Point', ['x', 'y'])
>>> p = Point(x=1.0, y=2.0)
>>> p
Point(x=1.0, y=2.0)
>>> p.x
1.0
>>> p.y
2.0
>>> class Point(collections.namedtuple('PointBase', ['x', 'y'])):
...     __slots__ = ()
...     def __add__(self, other):
...         return Point(x=self.x + other.x, y=self.y + other.y)
...
>>> p = Point(x=1.0, y=2.0)
>>> q = Point(x=2.0, y=3.0)
>>> p + q
Point(x=3.0, y=5.0)

Tập hợp cùng tuần số xuất hiện

>>> import collections
>>> A = collections.Counter([1, 2, 2])
>>> B = collections.Counter([2, 2, 3])
>>> A
Counter({2: 2, 1: 1})
>>> B
Counter({2: 2, 3: 1})
>>> A | B
Counter({2: 2, 1: 1, 3: 1})
>>> A & B
Counter({2: 2})
>>> A + B
Counter({2: 4, 1: 1, 3: 1})
>>> A - B
Counter({1: 1})
>>> B - A
Counter({3: 1})

Phần tử xuất hiện nhiều nhất

>>> import collections
>>> A = collections.Counter([1, 1, 2, 2, 3, 3, 3, 3, 4, 5, 6, 7])
>>> A
Counter({3: 4, 1: 2, 2: 2, 4: 1, 5: 1, 6: 1, 7: 1})
>>> A.most_common(1)
[(3, 4)]
>>> A.most_common(3)
[(3, 4), (1, 2), (2, 2)]

Hàng đợi hai đầu

>>> import collections
>>> Q = collections.deque()
>>> Q.append(1)
>>> Q.appendleft(2)
>>> Q.extend([3, 4])
>>> Q.extendleft([5, 6])
>>> Q
deque([6, 5, 2, 1, 3, 4])
>>> Q.pop()
4
>>> Q.popleft()
6
>>> Q
deque([5, 2, 1, 3])
>>> Q.rotate(3)
>>> Q
deque([2, 1, 3, 5])
>>> Q.rotate(-3)
>>> Q
deque([5, 2, 1, 3])

Hàng đợi hai đầu có giới hạn độ dài

>>> import collections
>>> last_three = collections.deque(maxlen=3)
>>> for i in range(10):
...     last_three.append(i)
...     print(', '.join(str(x) for x in last_three))
...
0
0, 1
0, 1, 2
1, 2, 3
2, 3, 4
3, 4, 5
4, 5, 6
5, 6, 7
6, 7, 8
7, 8, 9

Dict có thứ tự

>>> m = dict((str(x), x) for x in range(10))
>>> print(', '.join(m.keys()))
4, 6, 8, 2, 3, 7, 0, 9, 5, 1
>>> import collections
>>> m = collections.OrderedDict((str(x), x) for x in range(10))
>>> print(', '.join(m.keys()))
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
>>> m = collections.OrderedDict((str(x), x) for x in range(10, 0, -1))
>>> print(', '.join(m.keys()))
10, 9, 8, 7, 6, 5, 4, 3, 2, 1

Dict với giá trị mặc định

>>> m = dict()
>>> m['a']
Traceback (most recent call last):
  File "", line 1, in 
KeyError: 'a'
>>> import collections
>>> m = collections.defaultdict(int)
>>> m['a']
0
>>> m['b']
0
>>> m = collections.defaultdict(str)
>>> m['a']
''
>>> m['b'] += 'a'
>>> m
defaultdict(, {'b': 'a', 'a': ''})
>>> m = collections.defaultdict(lambda: '[default value]')
>>> m['a']
'[default value]'

Cấu trúc cây với default dict

>>> import collections
>>> import json
>>> tree = lambda: collections.defaultdict(tree)
>>> root = tree()
>>> root['menu']['id'] = 'file'
>>> root['menu']['value'] = 'File'
>>> root['menu']['menuitems']['new']['value'] = 'New'
>>> root['menu']['menuitems']['new']['onclick'] = 'new();'
>>> root['menu']['menuitems']['open']['value'] = 'Open'
>>> root['menu']['menuitems']['open']['onclick'] = 'open();'
>>> root['menu']['menuitems']['close']['value'] = 'Close'
>>> root['menu']['menuitems']['close']['onclick'] = 'close();'
>>> root
defaultdict( at 0x7f5ce09e4488>, {'menu': defaultdict( at 0x7f5ce09e4488>, {'value': 'File', 'menuitems': defaultdict( at 0x7f5ce09e4488>, {'new': defaultdict( at 0x7f5ce09e4488>, {'value': 'New', 'onclick': 'new();'}), 'close': defaultdict( at 0x7f5ce09e4488>, {'value': 'Close', 'onclick': 'close();'}), 'open': defaultdict( at 0x7f5ce09e4488>, {'value': 'Open', 'onclick': 'open();'})}), 'id': 'file'})})
>>> print(json.dumps(root, sort_keys=True, indent=4, separators=(',', ': ')))
{
    "menu": {
        "id": "file",
        "menuitems": {
            "close": {
                "onclick": "close();",
                "value": "Close"
            },
            "new": {
                "onclick": "new();",
                "value": "New"
            },
            "open": {
                "onclick": "open();",
                "value": "Open"
            }
        },
        "value": "File"
    }
}

Sinh uniqe id cho từng giá trị

>>> import collections
>>> import itertools
>>> value_to_numeric_map = collections.defaultdict(itertools.count().__next__)
>>> value_to_numeric_map['a']
0
>>> value_to_numeric_map['b']
1
>>> value_to_numeric_map['c']
2
>>> value_to_numeric_map['a']
0
>>> value_to_numeric_map['b']
1

Những phần tử lớn nhất và nhỏ nhất trong 1 list

>>> import heapq
>>> import random
>>> a = [random.randint(0, 100) for __ in range(100)]
>>> a
[77, 59, 53, 12, 57, 81, 90, 67, 62, 6, 93, 35, 28, 45, 32, 95, 55, 52, 0, 19, 99, 47, 3, 74, 15, 81, 69, 73, 94, 37, 51, 58, 36, 51, 57, 96, 15, 65, 4, 42, 42, 0, 36, 89, 34, 73, 12, 62, 13, 34, 84, 51, 92, 37, 17, 56, 59, 15, 8, 31, 36, 90, 70, 95, 41, 56, 100, 84, 50, 91, 72, 43, 15, 12, 90, 34, 58, 97, 72, 67, 79, 28, 84, 9, 25, 75, 47, 43, 100, 9, 27, 86, 12, 90, 4, 19, 45, 62, 91, 76]
>>> heapq.nsmallest(5, a)
[0, 0, 3, 4, 4]
>>> heapq.nlargest(5, a)
[100, 100, 99, 97, 96]

Ứng dụng của itertools

Tích Descartes

>>> import itertools
>>> for p in itertools.product('123', '45'):
...     print(''.join(p))
...
14
15
24
25
34
35
>>> for p in itertools.product('12', repeat=4):
...     print(''.join(p))
...
1111
1112
1121
1122
1211
1212
1221
1222
2111
2112
2121
2122
2211
2212
2221
2222

Tổ hợp

>>> import itertools
>>> for c in itertools.combinations('12345', 3):
...    print(''.join(c))
...
123
124
125
134
135
145
234
235
245
345
>>> for c in itertools.combinations_with_replacement('12345', 2):
...    print(''.join(c))
...
11
12
13
14
15
22
23
24
25
33
34
35
44
45
55

Chỉnh hợp

>>> import itertools
>>> for p in itertools.permutations('1234', 3):
...    print(''.join(p))
...
123
124
132
134
142
143
213
214
231
234
241
243
312
314
321
324
341
342
412
413
421
423
431
432

Ghép các iterable

>>> import itertools
>>> a = [1, 2, 3, 4]
>>> for p in itertools.chain(itertools.combinations(a, 2), itertools.combinations(a, 3)):
...     print(p)
...
(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
(1, 2, 3)
(1, 2, 4)
(1, 3, 4)
(2, 3, 4)
>>> for subset in itertools.chain.from_iterable(itertools.combinations(a, n) for n in range(len(a) + 1)):
...     print(subset)
...
()
(1,)
(2,)
(3,)
(4,)
(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
(1, 2, 3)
(1, 2, 4)
(1, 3, 4)
(2, 3, 4)
(1, 2, 3, 4)

Nhóm các phần tử theo một tiêu chí

>>> import itertools
>>> for k, g in itertools.groupby('122333444455555'):
...     print(k, ''.join(g))
...
1 1
2 22
3 333
4 4444
5 55555
>>> m = {'a': 1, 'b': 2, 'c': 1, 'd': 2}
>>> sorted_m = dict(sorted(m.items(), key=lambda x: x[1]))
>>> for k, g in itertools.groupby(sorted_m, lambda x: x[1]):
...     print(k, ', '.join(e[0] for e in g))
...
1 c, a
2 b, d

Tham số của startswith

>>> s = 'http://google.com'
>>> s.startswith('http://') or s.startswith('https://')
True
>>> s.startswith(('http://', 'https://'))
True

Tương tự với endswithisinstance

>>> s.endswith('.com') or s.endswith('.net')
True
>>> s.endswith(('.com', '.net'))
True
>>> isinstance(1, (int, float))
True

Trong trình thông dịch, _ sẽ lưu giá trị phép tính cuối cùng

>>> 1 + 2
3
>>> _
3
>>> _ + 1
4
>>> foo = 'bar'
>>> foo
'bar'
>>> _ + 'foo'
'barfoo'

Tham số mặc định là mutable thì phải cẩn thận

Điều này đã được nhắc nhiều khi nói đến "Idiomatic Python"

>>> def foo(l=[]):
...     l.append(1)
...     print(l)
...
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]
>>> def foo(l=None):
...     l = l or []
...     l.append(1)
...     print(l)
...
>>> foo()
[1]
>>> foo()
[1]
>>> foo()
[1]

Mở một server HTTP đơn giản

python3 -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 ...
127.0.0.1 - - [24/Jul/2017 13:56:51] "GET / HTTP/1.1" 200 -

So sánh theo phong cách "toán học"

>>> x = 2
>>> 3 > x == 1
False
>>> 1 < x < 3
True
>>> 10 < 10*x < 30
True
>>> 10 < x**5 < 30
False
>>> 100 < x*100 >= x**6 + 34 > x <= 2*x < 5
True

Đảo ngược list

>>> list(reversed([1, 2, 3, 4]))
[4, 3, 2, 1]
>>> [1, 2, 3, 4][::-1]
[4, 3, 2, 1]
>>> tuple(reversed((1, 2, 3, 4)))
(4, 3, 2, 1)
>>> (1, 2, 3, 4)[::-1]
(4, 3, 2, 1)

Chuyển iterable thành string

>>> x = ['Hello', 'world', '!']
>>> ' '.join(x)
'Hello world !'

Class của Python có thể thay đổi tùy ý

>>> class Foo:
...     def one(self):
...         return 1
...
>>> c = Foo()
>>> c.one()
1
>>> def two(self):
...     return 2
...
>>> Foo.two = two
>>> c.two()
2

Hiển thị thuộc tính của 1 đối tượng

>>> x = [1, 2, 3]
>>> dir(x)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

Check dung lượng bộ nhớ mà đối tượng chiếm giữ

>>> x = [1, 2, 3]
>>> import sys
>>> sys.getsizeof(x)
88

Đặt breakpoint để debug

>>> import pdb
>>> for i in range(10):
...     if i == 5:
...         pdb.set_trace()
...
> (1)()
(Pdb) i
5

Zen of Python

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!