Python 是一種動態且強型別的程式語言。它透過型別提示,同時採用鴨子型別與漸進式型別。
雖然 Python 支援許多不同的程式設計風格,但在內部,Python 裡的萬物都是物件。這包括數字、字串、陣列,甚至函式。
隨著我們在這條 track 上繼續前進,之後會更深入探討這一切的意義。
這個第一個練習會介紹 Python 的 4 項主要語言特性:
def關鍵字與return關鍵字),一般來說,Python track 的內容、測試與分析工具,都遵循 PEP 8 與 PEP 257 所列出的 Python 程式碼風格慣例,並額外(強烈)建議不要使用單一字母的變數名稱,也不要使用名為 "_" 的變數。
在 Python track 上,變數一律以 snake_case 撰寫,常數則使用 SCREAMING_SNAKE_CASE。
程式設計師可以使用賦值運算子=,把名稱(也稱為變數)綁定到任何型別的物件上:<name> = <value>。
一個名稱在其生命周期中,可以重新賦值(或重新綁定)成不同的值(不同的物件型別)。
>>> my_first_variable = 1 #<-- my_first_variable bound to an integer object of value one.
>>> my_first_variable = 2 #<-- my_first_variable re-assigned to integer value 2.
>>> print(type(my_first_variable))
<class 'int'>
>>> print(my_first_variable)
2
>>> my_first_variable = "Now, I'm a string." #<-- You may re-bind a name to a different object type and value.
>>> print(type(my_first_variable))
<class 'str'>
>>> my_first_variable = 'You can call me "str".' #<-- Strings can be declared using single or double quote marks.
>>> print(my_first_variable)
You can call me "str".
常數是程式中只應該賦值一次的名稱。
它們應該定義在模組(檔案)層級,而且通常程式中所有函式與類別都能看見。
使用 SCREAMING_SNAKE_CASE 表示這個名稱不應該重新賦值,其值也不應該被改動。
def關鍵字會開啟一段函式定義。
每個函式可以在()括號中帶有零個或多個正式的參數,後面接著一個:冒號。
函式主體的敘述從def的下一行開始,而且必須縮排在同一區塊中。
# The body of a function is indented by 2 spaces, & prints the sum of the numbers.
def add_two_numbers(number_one, number_two):
total = number_one + number_two
print(total)
>>> add_two_numbers(3, 4)
7
# Inconsistent indentation in your code blocks will raise an error.
>>> def add_three_numbers_misformatted(number_one, number_two, number_three):
... result = number_one + number_two + number_three # This was indented by 4 spaces.
... print(result) #this was only indented by 3 spaces
...
...
File "<stdin>", line 3
print(result)
^
IndentationError: unindent does not match any outer indentation level
函式會透過return關鍵字明確地回傳一個值或物件:
# Function definition on first line, explicit return used on final line.
>>> def add_two_numbers(number_one, number_two):
return number_one + number_two
# Calling the function in the Python shell returns the sum of the numbers.
>>> add_two_numbers(3, 4)
7
# Assigning the function call to a variable and printing it
# will also return the value.
>>> sum_with_return = add_two_numbers(5, 6)
>>> print(sum_with_return)
11
如果一個return後面沒有明確的運算式,函式就會隱式地回傳None物件。
None的細節會在之後的練習中介紹。
就這個練習與這段說明而言,None是一個佔位符,代表空無,或 null:
# This function will return `None`
def square_a_number(number):
square = number * number
return # <-- note that this return is not followed by an expression
# Calling the function in the Python shell appears
# to not return anything at all.
>>> square_a_number(2)
>>>
# Using print() with the function call shows that
# the function is actually returning the **None** object.
>>> print(square_a_number(2))
None
省略return的函式同樣會隱式地回傳None物件。
這表示如果你在函式中沒有使用return,Python 會替你回傳None物件。
# This function omits a return keyword altogether.
def add_two_numbers(number_one, number_two):
result = number_one + number_two
>>> add_two_numbers(5, 7)
>>> print(add_two_numbers(5, 7))
None
# Assigning the function call to a variable and printing
# the variable will also show None.
>>> sum_without_return = add_two_numbers(5, 6)
>>> print(sum_without_return)
None
函式是透過在名稱後面加上()來呼叫或叫用。
點號(.)標記法用於呼叫定義在類別或模組內的函式。
>>> def raise_to_power(number, power):
... return number ** power
...
>>> raise_to_power(3,3) # <--Invoking the function with the arguments 3 and 3.
27
# A mismatch between the number of parameters and the number of arguments will raise an error.
>>> raise_to_power(4,)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: raise_to_power() missing 1 required positional argument: 'power'
# Calling methods or functions in classes and modules.
>>> start_text = "my silly sentence for examples."
>>> str.upper(start_text) # <--Calling the upper() method from the built-in str class on start_text.
'MY SILLY SENTENCE FOR EXAMPLES.'
# Importing the math module
>>> import math
>>> math.pow(2,4) # <--Calling the pow() function from the math module.
16.0
Python 的註解以不屬於字串一部分的#開頭,並在該行結束時結束。
與許多其他程式語言不同,Python 不支援多行註解符號。
註解區塊的每一行都必須以#字元開頭。
函式主體的第一個敘述可以選擇性地是文件字串,用來簡潔地概述函式或物件的用途。 文件字串使用三重雙引號(""")宣告,並縮排到與程式碼區塊相同的層級:
# An example from PEP257 of a multi-line docstring
# reformatted to use Google style non-type hinted docstrings.
# Some additional details can be found in the Sphinx documentation:
# https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html#getting-started
def complex(real=0.0, imag=0.0):
"""Form a complex number.
Keyword Arguments:
real (float): The real part of the number (default 0.0)
imag (float): The imaginary part of the number (default 0.0)
"""
if imag == 0.0 and real == 0.0:
return complex_zero
文件字串會被 Sphinx 這類自動化文件工具讀取,也可以透過在函式、方法或類別名稱上呼叫特殊屬性.__doc__來取得。
一般的文件字串慣例記載於 PEP257,但確切的格式會因專案與團隊而異。
Exercism 的概念練習會盡量遵循 Google 風格,適用於沒有型別提示的程式碼。
文件字串也可以當作輕量單元測試,這會在之後的練習中介紹。
# An example on a user-defined function using a Google style docstring.
>>> def raise_to_power(number, power):
"""Raise a number to an arbitrary power.
Parameters:
number (int): The base number.
power (int): The power to raise the base number to.
Returns:
int: The number raised to the specified power.
Takes a number and raises it to the specified power, returning the result.
"""
return number ** power
...
# Calling the .__doc__ attribute of the function and printing the result.
>>> print(raise_to_power.__doc__)
Raise a number to an arbitrary power.
Parameters:
number (int): The base number.
power (int): The power to raise the base number to.
Returns:
int: The number raised to the specified power.
Takes a number and raises it to the specified power, returning the result.
你將寫一些程式碼,幫你照著最愛的食譜做出美味的千層麵。
你有五個任務,全都和烹煮這道食譜有關。
我們已經在起始檔案裡幫你寫好了第一個函式定義,但剩下的函式定義需要你自己寫。 你也需要自己定義所有的常數。 請仔細閱讀起始檔案裡的 #TODO 註解行。 完成一個任務後,就把 TODO 註解刪掉。
定義 EXPECTED_BAKE_TIME 常數,表示千層麵應該在烤箱中烘焙幾分鐘。
根據你的食譜,千層麵應該在烤箱裡烤 40 分鐘:
>>> print(EXPECTED_BAKE_TIME)
40
完成 bake_time_remaining() 函式,它接受千層麵實際已在烤箱中的分鐘數作為引數,並根據 EXPECTED_BAKE_TIME 常數回傳千層麵還需要烘焙幾分鐘。
>>> bake_time_remaining(30)
10
定義 preparation_time_in_minutes() 函式,它接受你想加到千層麵的 number_of_layers 作為引數,並回傳製作這些分層需要花費幾分鐘。
假設每一層需要 2 分鐘準備。
>>> def preparation_time_in_minutes(number_of_layers):
...
...
>>> preparation_time_in_minutes(2)
4
定義 elapsed_time_in_minutes() 函式,它接受兩個參數作為引數:
number_of_layers(加到千層麵的分層數量)elapsed_bake_time(千層麵已經在烤箱中烘焙的分鐘數)。這個函式應該回傳你在廚房烹飪的總分鐘數,也就是你分層準備的時間,加上千層麵在烤箱中烘焙的時間。
>>> def elapsed_time_in_minutes(number_of_layers, elapsed_bake_time):
...
...
>>> elapsed_time_in_minutes(3, 20)
26
回頭翻閱整份食譜,以 函式文件字串 的形式加上「註記」。
def elapsed_time_in_minutes(number_of_layers, elapsed_bake_time):
"""Calculate the elapsed cooking time.
Parameters:
number_of_layers (int): The number of layers in the lasagna.
elapsed_bake_time (int): Time the lasagna has been baking in the oven.
Returns:
int: The total time elapsed (in minutes) preparing and baking.
This function takes two integers representing the number of lasagna
layers and the time already spent baking the lasagna. It calculates
the total elapsed minutes spent cooking (preparing + baking).
"""