天天看點

COMP9021筆記數字numbers字元串string清單list元組tuple集合set字典dictionary一些内置方法檔案處理關于類與繼承一些常見的困惑

這篇文章持續更新一些學習這門課時文法方面踩過的坑/遇到的問題,如果有錯誤的地方歡迎交流指正。

文章目錄

  • 數字numbers
  • 字元串string
  • 清單list
    • 切片slice
    • 清單生成式list comprehension
  • 元組tuple
  • 集合set
  • 字典dictionary
  • 一些内置方法
  • 檔案處理
  • 關于類與繼承
    • 類的屬性
    • 類的方法
  • 一些常見的困惑
    • 關于main
    • 關于Python命名規則
    • 什麼是Foo?

數字numbers

  1. 關于float和int的強制類型轉換:
    • float()方法可以接受的參數類型包括代表整數/浮點數的字元串、整數
    • int()方法可以接收到參數類型包括代表整數的字元串、浮點數
    • 如果将一個代表浮點數的字元串傳給

      int()

      ,那麼會引起

      ValueError

    >>> int('5')
    5
    >>> float('5.0')
    5.0
    >>> float('5')
    5.0
    >>> int(5.0)
    5
    >>> float(5)
    5.0
    >>> int('5.0')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: invalid literal for int() with base 10: '5.0'
    >>> int(float('5.0'))
    5
               
  2. 将數字按n位輸出(補0)的兩種方式,請看下面例子:
    # 将數字num按6位輸出,差位補0
    num = 123
    # 方法1:f-string格式控制
    print(f'{num:06}')  # 000123
    # 如果是 print(f'{num:6}') 則輸出   123
    
    # 方法2:str.zfill()
    num_str = str(num)
    result = num_str.zfill(6)  # 字元串右對齊補0
    print(result)  # 000123
               
  3. 将n進制(2 <= n <= 36)數字num轉化為10進制數輸出:

    可以使用int(str, base)方法,

    str

    接收一個代表數字的字元串,

    base

    接收這個數字所使用的進制。該方法傳回一個int類型的數字
    >>> num1 = 101010
    >>> print(int(str(num1), 2))
    42
    >>> num2 = 123456
    >>> print(int(str(num2), 7))
    22875
    >>> num3_str = '123456'
    >>> t = int(num3_str, 7)
    >>> print(t)
    22875
    >>> print(type(t))
    <class 'int'>
               
  4. round() 函數的進位準則

    奇進偶舍是一種比較精确比較科學的計數保留法,是一種數字修約規則。具體要求如下(以保留兩位小數為例):

    • 要求保留位數的後一位如果是4或者4以下的數字,則舍去, 例如 5.214保留兩位小數為5.21。
    • 如果保留位數的後一位如果是6或者6以上的數字,則進上去, 例如5.216保留兩位小數為5.22。
    • 如果是一位小數保留整數部分 且 小數部分是5,則根據整數部分個位數(奇進偶舍)決定保留結果。
    • 如果是n位小數保留n-1位,且第n位小數是5,則要根據第n-1位的小數(奇進偶舍)決定保留結果。
    • 如果保留位數的後一位如果是5,且該位數後有數字,則應進上去。例如5.2152保留兩位小數為5.22,5.2252保留兩位小數為5.23,5.22500001保留兩位小數為5.23。
      >>> round(5.215,2)#實際并沒有進位
      5.21
      >>> round(5.225,2)
      5.22
      >>>
      >>> round(1.5)#此處進位
      2
      >>> round(1.5)==round(2.5)#偶數舍去
      True
      >>> round(1.15,1)
      1.1
      >>> round(1.25,1)
      1.2
      >>> round(1.151,1)
      1.2
      >>> round(1.251,1)
      1.3
                 
    • 從統計學的角度,“奇進偶舍”比“四舍五入”要科學,在大量運算時,它使舍入後的結果誤差的均值趨于零,而不是像四舍五入那樣逢五就入,導緻結果偏向大數,使得誤差産生積累進而産生系統誤差,“奇進偶舍”使測量結果受到舍入誤差的影響降到最低。
    • NB:Python由于浮點數的精度問題,它不是嚴格的“奇進偶舍”,例如官方文檔中的例子:
      The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float. See Floating Point Arithmetic: Issues and Limitations for more information.
      至于原因,可以參考Python中關于round函數的小坑中的解釋:
      這跟浮點數的精度有關。我們知道在機器中浮點數不一定能精确表達,因為換算成一串1和0後可能是無限位數的,機器已經做出了截斷處理。那麼在機器中儲存的2.675這個數字就比實際數字要小那麼一點點。這一點點就導緻了它離2.67要更近一點點,是以保留兩位小數時就近似到了2.67。

字元串string

  1. str.issapce():如果字元串中隻包含空白,則傳回 True,否則傳回 False
  2. 避免在循環中用+和+=操作符來累加字元串. 由于字元串是不可變的, 這樣做會建立不必要的臨時對象, 并且導緻二次方而不是線性的運作時間. 作為替代方案, 你可以将每個子串加入清單, 然後在循環結束後用

    .join

    連接配接清單. (也可以将每個子串寫入一個 cStringIO.StringIO 緩存中.)
  3. fstring是Python3.6版本之後一種很靈活的控制字元串輸出的方式,這篇博文有很詳細的介紹。

    關于如何用變量指定浮點數輸出寬度,可以參考下面這種做法:

    num = 12345.678
    width = 10
    # 保留兩位小數
    print(f"{num:.2f}")  # 12345.68
    # 保留兩位小數,width個占位符,不足的使用0補充
    print(f"{num:0{width}.2f}")  # 0012345.68
               
  4. [:-1]

    對于Python的字元串中意味着什麼?
    >>> 'test\n'
    'test\n'
    >>> 'test\n'[:-1]
    'test'
               

    因為它對空字元串也是有效的,是以它在移除 假若存在的最末位的字元(包括\n\r\t等) 時非常安全

    切片不僅對字元串有效,對任何序列都有效。

    對于檔案中的line,可以使用

    line.rstrip('\n')

    來删除最後的換行符。但有時候檔案最後一行并不是以換行符結束(而是以EOF-end of file),這時就可以用切片來移除末尾行最後任意一個符号。
  5. 在 str.rstrip([chars]) 中,當chars由n個字元組成時(即chars=char1char2char3…charn),不能将chars視作一個字元串。

    傳回的新字元串會把str末尾所有屬于chars的char都删除,直到遇到一個非chars的字元為止。

    str.lstrip([chars])

    同理
    s1 = "[email protected]'@#@x@#x"
    print(s1.rstrip('@#x'))  # 輸出結果是"[email protected]'"而不是"[email protected]'@#@x"
    print(s1.rstrip('@''#''x'))  # 輸出結果是"[email protected]'"而不是"[email protected]"或"[email protected]@#@x"
    # 下面這兩種寫法是錯誤的 
    # print(s1.rstrip('@', '#', 'x'))
    # 會報錯TypeError: rstrip expected at most 1 arguments, got 3
    # print(s1.rstrip(['@', '#', 'x']))
    # 會報錯TypeError: rstrip arg must be None or str
               
  6. index() 方法檢測字元串中是否包含子字元串 str ,如果指定 beg(開始) 和 end(結束) 範圍,則檢查是否包含在指定範圍内,在的話傳回索引位置。該方法與 python find()方法一樣,隻不過如果str不在 string中會報一個異常,而find方法不在的話傳回-1。

清單list

切片slice

  1. 清單的append()方法傳回值是None Type,它隻能用于修改原清單,無法連續嵌套使用,例如這樣的寫法是不合法的
    list1 = [1]
    list1.append(2).append(3)  # 錯誤寫法
               
  2. 清單切片中的深複制與淺複制,請看下面代碼
    a = [1, 2, 3, 4, 5, 6]
    b = a[:3]  # 淺複制,修改清單a的值不影響清單b的值
    c = a  # 深複制,清單a與清單c指向同一處記憶體位址,其中一個改變,另一個随着改變
    a[:3] = [6, 7, 8]
    print(a)  # [6, 7, 8, 4, 5, 6]
    print(b)  # [1, 2, 3]
    print(c)  # [6, 7, 8, 4, 5, 6]
               
  3. 二維數組的切片:對一個二維數組,想取其中的某一列元素,該怎麼操作呢?

    請看下面這個例子:

    # 現有一個二維數組a,想取其中第二列元素[2, 5, 6]
    a =[[1,2,3],
    	[4,5,6],
    	[7,8,9]]
    # 先來看幾個錯誤的嘗試:
    print(a[0:3][1:2])  # [[4, 5, 6]]
    # 上面那行代碼實際上是先對a做了切片[0:3]得到[[1,2,3],[4,5,6],[7,8,9]],再對其做切片[1:2]得到[[4, 5, 6]]
    # 同理下面這行代碼是先對a做了切片[1:2]得到[[4,5,6]],再對其做切片[0:3]得到[[4, 5, 6]]
    print(a[1:2][0:3])  # 
    
    # 這種寫法也是錯誤的:
    # print(a[:, 1])
    # TypeError: list indices must be integers or slices, not tuple
    
    # 正确的寫法:
    b = [i[1] for i in a]
    print(b)  # [2, 5, 8]
               

清單生成式list comprehension

清單生成式/清單推導式/清單解析式:清單推導式提供了從序列建立清單的簡單途徑。通常應用程式将一些操作應用于某個序列的每個元素,用其獲得的結果作為生成新清單的元素,或者根據确定的判定條件建立子序列。

每個清單推導式都在 for 之後跟一個表達式(表達式可以是任意的,意思是你可以在清單中放入任意類型的對象),然後有零到多個 for 或 if 子句(各語句之間是嵌套關系)。傳回結果是一個根據表達從其後的 for 和 if 上下文環境中生成出來的清單。

另:如果希望表達式推導出一個元組,此時元組的括号不可省略

# 對每個元素進行操作
>>> seq = [2, 4, 6]
>>> [3*x for x in seq]
[6, 12, 18]

# 生成清單嵌套清單
>>> [[x, x**2] for x in seq]
[[2, 4], [4, 16], [6, 36]]

# 對序列中每個元素調用某個方法
>>> freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']

# 用if子句對序列元素進行過濾
>>> [3*x for x in seq if x > 3]
[12, 18]
>>> [3*x for x in seq if x < 2]
[]

# 不同元素來自于不同序列
>>> vec1 = [2, 4, 6]
>>> vec2 = [4, 3, -9]
>>> [x*y for x in vec1 for y in vec2]
[8, 6, -18, 16, 12, -36, 24, 18, -54]
>>> [x+y for x in vec1 for y in vec2]
[6, 5, -7, 8, 7, -5, 10, 9, -3]
>>> [vec1[i]*vec2[i] for i in range(len(vec1))]
[8, 12, -54]

# 清單推導式可以使用複雜表達式或者嵌套函數
>>> [str(round(355/113, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']
           

清單推導式的執行順序:左邊第二個語句是最外層,依次往右進一層;左邊第一條語句是最後一層。

# 清單推導式的執行順序:左邊第二個語句是最外層,依次往右進一層;左邊第一條語句是最後一層。
   [x*y for x in range(1,5) if x > 2 for y in range(1,4) if y < 3]
   
   # 執行順序
   list1 = [] 
   for x in range(1,5):
       if x > 2:
           for y in range(1,4):
               if y < 3:
                   list1.append(x * y)
   
   # 該清單為[3, 6, 4, 8]
           

在一個清單生成式中,for前面的if … else是表達式,而for後面的if是過濾條件,不能帶else

[x if x % 2 == 0 else -x for x in range(1, 11)]
# 輸出[-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]

 [x if x % 2 == 0 for x in range(1, 11)]
 	# 報錯
 	# File "<stdin>", line 1
 	# [x if x % 2 == 0 for x in range(1, 11)]
   #                   ^
   # SyntaxError: invalid syntax
           

元組tuple

  1. 元組用"()"辨別,内部元素用逗号隔開。但是元組不能二次指派,相當于隻讀清單

集合set

  1. s.update( "字元串" )

    s.update( {"字元串"} )

    含義不同:

    s.update( {"字元串"} )

    将字元串添加到集合中,有重複的會忽略。

    s.update( "字元串" )

    将字元串包含的每個字元逐個添加到集合中,有重複的會忽略。
    >>> s = set(("Google", "Runoob", "Taobao"))
    >>> print(s)
    {'Google', 'Runoob', 'Taobao'}
    >>> s.update({"Facebook"})
    >>> print(s) 
    {'Google', 'Runoob', 'Taobao', 'Facebook'}
    >>> s.update("Yahoo")
    >>> print(s)
    {'h', 'o', 'Facebook', 'Google', 'Y', 'Runoob', 'Taobao', 'a'}
    >>>
               
  2. s.intersection()

    不改變原集合隻傳回取交集的結果

    s.intersection_update()

    改變原集合,不傳回值

    s.difference()

    s.difference_update()

    s.symmetric_difference()

    s.symmetric_difference_update()

    同理

    s.union()

    不改變原集合隻傳回取并集的結果

    注意,沒有

    s.union_update()

    方法,想将原集合修改為與其他集合取并集的結果應使用

    s.update()

    方法
    >>> a = {1,2,3}
    >>> b = {3,4,5}
    >>> a.intersection(b)
    {3}
    >>> a
    {1, 2, 3}
    >>> a.intersection_update(b)
    >>> a
    {3}
    >>> a.union(b)
    {3, 4, 5}
    >>> a
    {3}
    >>> a.union_update(b)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'set' object has no attribute 'union_update'
    >>> a.update(b)
    >>> a
    {3, 4, 5}
               

字典dictionary

  1. Python 字典 items() 方法以 ‘dict_items’ 類型傳回可周遊的(鍵, 值) 元組數組。

    dict.items()

    常用

    for k, v in dict.items()

    來周遊字典
  2. 清單是有序的對象結合,字典是無序的對象集合。兩者之間的差別在于:字典當中的元素是通過鍵來存取的,而不是通過偏移存取
  3. 字典的key值必須是可哈希的
  4. 關于字典的參考資料:

    Python3如何将兩個清單合并成字典

    Python字典 你必須知道的用法系列

    list,tuple,dict的資料結構

一些内置方法

  1. enumerate() 函數用于将一個可周遊的資料對象(如清單、元組或字元串)組合為一個索引序列(對象),同時列出資料和資料下标,一般用在 for 循環當中

    enumerate(sequence, [start=0])

    >>>seasons = ['Spring', 'Summer', 'Fall', 'Winter']
    
    >>> list(enumerate(seasons)) 
    [(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')] 
    
    >>> list(enumerate(seasons, start=1))  # 下标從 1 開始 [(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
    
    >>> seq = ['one', 'two', 'three']
    >>> for i, element in enumerate(seq):
    ...     print(i, element)
    ... 
    0 one
    1 two
    2 three
               
  2. zip()函數用于将可疊代的對象作為參數,将對象中對應的元素打包成一個個元組,然後傳回由這些元組組成的一個可疊代對象,這樣做的好處是節約了不少的記憶體

    zip([iterable, ...])

    list(zip([iterable, ...]))

    機器學習模型訓練中,經常需要打亂資料集,用 zip() 函數可以實作如下:
    import random
    X = [1, 2, 3, 4, 5, 6]
    y = [0, 1, 0, 0, 1, 1]
    zipped_data = list(zip(X, y))  
    # 将樣本和标簽一 一對應組合起來,并轉換成list類型友善後續打亂操作
    random.shuffle(zipped_data)  
    # 使用random子產品中的shuffle函數打亂清單,原地操作,沒有傳回值
    new_zipped_data = list(map(list, zip(*zipped_data)))  
    # zip(*)反向解壓,map()逐項轉換類型,list()做最後轉換
    new_X, new_y = new_zipped_data[0], new_zipped_data[1]  
    # 傳回打亂後的新資料
    print('X:',X,'\n','y:',y)
    print('new_X:',new_X, '\n', 'new_y:',new_y)
               
  3. range() 的負數step與reversed() 函數

    range()函數傳回的是一個可疊代對象(非清單類型)

    range(stop)

    range(start, stop[, step])

    range的step參數為負數的邏輯是:先按正序的左閉右開區間取值,然後再反序輸出。而不是在左開右閉的區間裡反序取值
    # for i in range(a,b,-1)
    # 當a > b時,需要加第三個參數-1,代表倒序輸出
    # 倒序輸出range()時,仍然是在左閉右開區間内倒序,即取不到第二個參數
    for a in range(5,-3,-1):
        print(a)
    # 輸出5到-2
               

    reversed()函數傳回一個反轉的疊代器。

    可以對range(a,b)使用reversed(),相當與倒序周遊[a,b)

    for b in reversed(range(-3, 5)):
        print(b)
    # 輸出4到-3
               
  4. sorted()函數 week4重點

    sorted() 是Python3的内置函數,它可以對所有可疊代的對象進行排序操作,并且不改變原對象的值,傳回一個新的排序後的清單。

    sorted(iterable, key=None[, reverse=False])

    其中key可以為lambda函數

    如果想實作由大到小排序,可以令key值為負。也可以通過傳入第三個參數 reverse=True來實作反向排序。

    如果需要依靠多個元素排序,則用括号括起,依次聲明。例如:

    i代表傳入的第一個參數(一個可疊代對象,這裡是dict1.items())中的每一個元素。

    NB: sort() 是應用在list上的方法,它具有如下特性:

    • 這個方法會修改原始的 list(傳回值為None)
    • 通常這個方法不如sorted()友善
    • 如果你不需要原始的 list,list.sort()方法效率會稍微高一些

檔案處理

  1. f.readlines()傳回的是一個清單,包含檔案中包含的所有行。
    # 打開一個檔案
    f = open("/tmp/foo.txt", "r")  
    str = f.readlines()
    print(str)   
    # 關閉打開的檔案
    f.close() 
    # 輸出如下
    # ['Python 是一個非常好的語言。\n', '是的,的确非常好!!\n']
               
  2. open(filename, mode)

    将 mode 設定為 w+ 或 a+ 時,發現直接進行讀操作,得到的内容都是空,但原因不太相同:

    如果 mode 設定為 w+,即使沒有執行 write 操作,也會将檔案内容清空,是以這個時候直接進行讀草稿,讀到的是空内容。

    f = open("E:\\administrator\\Desktop\\test.txt", "w+")
     ```
    
    如果 mode 設定為 a+,檔案指針位置預設在最後面,因為讀内容時,是按照指針的位置往後讀,是以若指針位置在最後,讀出來即是空。在讀之前,一定要注意确認好指針位置是對的。
    
    ```python
    f = open("E:\\administrator\\Desktop\\test.txt", "a+")
    f.write("append content")
    print(f.tell())  #此時指針在檔案字元末尾處
    f.seek(0)
    print(f.tell())  # 指針回到0的位置
    str = f.read()
    print(str)
    f.close()f = open("E:\\administrator\\Desktop\\test.txt", "w+")
               

關于類與繼承

  1. Python中所有東西都是對象(objecet),每一個對象(objecet)都是由某個對象(objecet)建立的,每一個對象都是繼承自某種類型。有些對象(objecet)是類(class)
  2. 類,class,可以分為類的屬性和方法。Python中以雙下劃線開頭和結尾的屬性稱為特殊屬性,由于對象的方法也屬于屬性,是以以雙下劃線開頭和結尾的方法稱為特殊方法。
  3. 定義類的參數時,預設順序為:位置參數positional arguments,可變參數,預設參數。位置參數應該始終在可變參數之前,否則會被傳入到可變參數内,視為可變參數的一部分
  4. ?如果函數的參數清單第n位是

    *

    ,那麼第n位後的參數必須以

    arg_name=arg

    的形式傳入,否則就會報錯。可以用這種方法強制使用者輸入參數對應的值
  5. 子類a想要繼承父類A,隻需要在定義子類時将父類名稱寫在子類名稱後的括号裡,例如:
    class a(A):
    	def __init__(self, name):
    		self.name = name
               
  6. 子類會繼承父類的所有屬性和方法,可以重寫父類的屬性和方法,還可以定義屬于自己的屬性和方法。
  7. 一個類的執行個體被作為參數傳入另一個類時,該執行個體可以作為另一個類的屬性值。可以通過

    另一個類的執行個體.屬性(即類的執行個體).屬性的屬性(即類的執行個體的屬性)

    來調用
  8. isinstance(x, Class)

    可以用于判斷x是否為Class的一個執行個體,傳回True或False

類的屬性

  1. 通常我們都在類的__init__方法中定義類的屬性,文法

    self.屬性名 = 屬性

  2. Python支援在類的外部添加和删除屬性
    class Person:
    	def __init__(self, name, age):
    		self.name = name
    		if age < 0:
    			raise PersonException(“Age should be a positive integer!")
    		self.age = age
    
    # 執行個體化一個student
    student_1 = Person('Tony', 22)
    # 給student_1添加屬性degree
    student_1.degree = 'Bachelor'
    # 删除student_1的age屬性
    del student_1.age
               
  3. a.__name__

    傳回對象的名稱,比如類型(type, class)對象的名稱就是系統内置的或自定義的名稱字元串,類型的執行個體通常沒有屬性 __name__
  4. a.__class__

    傳回的是類型(type),等效于

    type(a)

  5. a.__base__

    傳回的是類(class)
  6. a.__bases__

    元組,包含 類型對象(type, class) C 的全部基類,類型的執行個體通常沒有屬性__bases__
  7. a.__dict__

    傳回a自身的各項屬性,但是不包括它從父類繼承的屬性
  8. dir(a)

    可以檢視a的所有屬性,包括自身屬性和從父類繼承的屬性
  9. 子類的初始化函數

    .__init__

    實際上是綁定在父類初始化函數上的

類的方法

  1. a.__repr__()

    等效于

    repr(a)

    ,會傳回<

    類名

    object at

    記憶體位址

    >,它是面向開發者的,要求準确無誤的指向對象
  2. a.__str__()

    等效于

    print(a)

    ,自定義傳回值時隻能是字元串,它是面向使用者的,具有更強的可讀性。
  3. 對于一個類a來說:
    • 如果隻定義了__repr__方法,

      repr(a)

      ,

      a.__repr__()

      ,

      print(a)

      ,

      a.__str__()

      都傳回.repr()方法的傳回值
    • 如果隻定義了__str__方法,

      repr(a)

      ,

      a.__repr__()

      傳回<

      類名

      object at

      記憶體位址

      >;

      print(a)

      ,

      a.__str__()

      傳回.str()方法的傳回值
    • 如果__repr__方法和__str__方法都有定義,則

      repr(a)

      ,

      a.__repr__()

      傳回.__repr__()方法的傳回值;

      print(a)

      ,

      a.__str__()

      傳回.__str__()方法的傳回值

一些常見的困惑

關于main

一些人不明白為什麼要在主程式前寫

if __name__ == '__main__':

在函數調用時,目前的程式名稱是main,被調用的程式名稱是其“檔案名”。這樣在調用上述函數的時候,if條件不滿足,各種檢驗不會運作。

因為即使是一個打算被用作腳本的檔案,也應該是可導入的。所有的頂級代碼在子產品導入時都會被執行。但如果簡單的導入導緻這個腳本的主功能(main functionality)被執行,這是不必要的。

是以主功能應該放在一個main()函數中,防止該腳本被導入時主功能被執行。

NB:不要去 調用函數、建立對象或者執行那些不應該在使用pydoc時被執行的操作。

關于Python命名規則

module_name  # 子產品名
package_name  # 包名
ClassName  # 類名
method_name  # 方法名
ExceptionName  # 異常名
function_name  # 函數名
GLOBAL_VAR_NAME  # 全局變量名
instance_var_name  # 執行個體變量名
function_parameter_name  # 函數參數名
local_var_name  # 本地變量名
           

命名約定

  1. 所謂”内部(Internal)”表示僅子產品内可用, 或者, 在類内是保護或私有的
  2. 用單下劃線(_)開頭表示子產品變量或函數是protected的(使用from module import *時不會包含)
  3. 用雙下劃線(__)開頭的執行個體變量或方法表示類内私有
  4. 将相關的類和頂級函數放在同一個子產品裡。不像Java,沒必要限制一個類一個子產品。
  5. 對類名使用大寫字母開頭的單詞(如CapWords, 即Pascal風格),但是子產品名應該用小寫加下劃線的方式(如lower_with_under.py)。盡管已經有很多現存的子產品使用類似于CapWords.py這樣的命名,但現在已經不鼓勵這樣做,因為如果子產品名碰巧和類名一緻,這會讓人困擾

應該避免的名稱

  1. 單字元名稱,除了計數器和疊代器。
  2. 包/子產品名中的連字元(-)
  3. 雙下劃線開頭并結尾的名稱(Python保留,例如__init__)

什麼是Foo?

Foo / **Bar **is an intentionally meaningless placeholder word often used in computer programming.常被作為函數/方法的名稱或變量名