一個認為一切根源都是“自己不夠強”的INTJ
個人主頁:用哲學編程-CSDN博客
專欄:每日一題——舉一反三
Python編程學習
Python內置函數
Python-3.12.0文檔解讀
目錄
我的寫法
各部分功能分析:
綜合時間復雜度
綜合空間復雜度
總結
思路擴充
方法1: 使用雙端隊列
方法2: 使用棧
方法3: 使用遞歸
方法4: 原地反轉
總結
哲學和編程思想
1.?簡潔性 (Simplicity)
2.?高內聚 (High Cohesion)
3.?面向表達式編程 (Expression-Oriented Programming)
4.?函數式編程 (Functional Programming)
5.?內置函數和標準庫的使用 (Leveraging Built-In Functions and Standard Library)
6.?聲明式編程 (Declarative Programming)
7.?最少驚訝原則 (Principle of Least Astonishment)
8.?單一職責原則 (Single Responsibility Principle)
9.?組合模式 (Composition over Inheritance)
總結
舉一反三
技巧1:簡潔性 (Simplicity)
技巧2:高內聚 (High Cohesion)
技巧3:面向表達式編程 (Expression-Oriented Programming)
技巧4:函數式編程 (Functional Programming)
技巧5:聲明式編程 (Declarative Programming)
技巧6:最少驚訝原則 (Principle of Least Astonishment)
技巧7:單一職責原則 (Single Responsibility Principle)
技巧8:組合模式 (Composition over Inheritance)
總結
題目鏈接
我的寫法
print(*input().split()[::-1])
?
這段代碼的功能是倒序輸出用戶輸入的一行文本中的單詞。
各部分功能分析:
- input():
- 等待用戶輸入一行文本,并返回輸入的字符串。
- 時間復雜度:O(n),其中 n 是輸入字符串的長度。
- 空間復雜度:O(n),用于存儲輸入的字符串。
- split():
- 將輸入的字符串按照空白字符(如空格)進行分割,返回一個包含各個單詞的列表。
- 時間復雜度:O(n),需要掃描整個輸入字符串。
- 空間復雜度:O(k),其中 k 是分割后的單詞列表的長度。每個單詞也是從輸入字符串中分割出來的,沒有額外的空間分配。
- [::-1]:
- 對分割后的單詞列表進行逆序操作。
- 時間復雜度:O(k),需要遍歷整個列表。
- 空間復雜度:O(k),會創建一個新的列表來存儲逆序后的元素。
- print(*...):
- 使用?*?運算符將列表的元素解包為單獨的參數傳遞給?print()?函數,從而實現倒序輸出每個單詞。
- 時間復雜度:O(k),需要遍歷每個單詞。
- 空間復雜度:O(1),print()?本身不需要額外的空間來存儲數據,但每個單詞會分別傳遞給?print()。
綜合時間復雜度
- 輸入操作:O(n)
- 分割操作:O(n)
- 逆序操作:O(k)
- 打印操作:O(k)
由于 n 是輸入字符串的長度,而 k 是分割后的單詞數,且 k <= n,可以認為綜合時間復雜度為 O(n)。
綜合空間復雜度
- 輸入字符串:O(n)
- 分割后的單詞列表:O(k)
- 逆序后的列表:O(k)
綜合空間復雜度為 O(n),因為存儲輸入字符串是主要的空間消耗。
總結
- 時間復雜度:O(n)
- 空間復雜度:O(n)
這段代碼非常簡潔且高效地實現了倒序輸出輸入行中的單詞。由于 Python 內置函數的高效實現,整體性能表現良好,適用于處理一般長度的輸入文本。
思路擴充
有其他方法可以實現同樣的功能。下面是另外幾種方法,包括一些使用不同編程范式和數據結構的實現方法。雖然這些方法的時間復雜度和空間復雜度未必能顯著超越原來的實現,但它們提供了不同的視角和編程技巧。
方法1: 使用雙端隊列
雙端隊列(deque)允許我們高效地在兩端插入和刪除元素。我們可以利用這一特性來實現反轉單詞的功能。
from collections import dequedef reverse_words_deque():import sysinput_line = sys.stdin.readline().strip()# 使用雙端隊列dq = deque()current_word = []for char in input_line:if char.isspace():if current_word:dq.appendleft(''.join(current_word))current_word = []else:current_word.append(char)if current_word:dq.appendleft(''.join(current_word))print(' '.join(dq))if __name__ == "__main__":reverse_words_deque()
方法2: 使用棧
棧的后進先出(LIFO)特性使得它非常適合這個任務。我們可以將單詞依次推入棧中,然后依次彈出即可實現反轉。
def reverse_words_stack():import sysinput_line = sys.stdin.readline().strip()stack = []current_word = []for char in input_line:if char.isspace():if current_word:stack.append(''.join(current_word))current_word = []else:current_word.append(char)if current_word:stack.append(''.join(current_word))while stack:print(stack.pop(), end=' ')print()if __name__ == "__main__":reverse_words_stack()
方法3: 使用遞歸
遞歸方法雖然不一定是最優的,但它提供了一種有趣的變換方式。
def reverse_words_recursive(words):if not words:returnword = words.pop()print(word, end=' ')reverse_words_recursive(words)def main_recursive():import sysinput_line = sys.stdin.readline().strip()words = input_line.split()reverse_words_recursive(words)print()if __name__ == "__main__":main_recursive()
方法4: 原地反轉
如果允許修改輸入字符串,可以考慮原地反轉。雖然Python字符串不可變,但我們可以用列表模擬這一操作。
def reverse_words_in_place():import sysinput_line = list(sys.stdin.readline().strip())def reverse_range(lst, start, end):while start < end:lst[start], lst[end] = lst[end], lst[start]start += 1end -= 1n = len(input_line)reverse_range(input_line, 0, n - 1)start = 0for i in range(n + 1):if i == n or input_line[i].isspace():reverse_range(input_line, start, i - 1)start = i + 1print(''.join(input_line))if __name__ == "__main__":reverse_words_in_place()
總結
以上幾種方法展示了如何從不同的角度實現“反轉單詞”的功能:
- 雙端隊列:高效的插入和刪除操作。
- 棧:利用后進先出的特性。
- 遞歸:雖然不一定高效,但提供了另一種實現思路。
- 原地反轉:模擬C語言風格的原地操作。
每種方法都有其獨特的應用場景和優缺點。從實際應用角度看,原始代碼已經足夠高效,但了解不同的實現方法能幫助你在不同場景中靈活應用。
哲學和編程思想
使用這段代碼解決問題不僅簡潔高效,還體現了多種重要的編程哲學和思想。以下是一些關鍵點:
1.?簡潔性 (Simplicity)
這段代碼采用了Python的內置函數和操作符,直接實現了功能,非常簡潔。簡潔性是編程中的一大美德,代碼越簡潔,越容易閱讀、理解和維護。
2.?高內聚 (High Cohesion)
這段代碼中的每個部分都有明確的職責:input()用于讀取輸入,split()用于分割單詞,[::-1]用于反轉列表,print(*...)用于輸出結果。這種高內聚性使得代碼更容易理解和調試。
3.?面向表達式編程 (Expression-Oriented Programming)
Python是一種表達式導向的語言,這段代碼充分利用了Python的表達式能力。通過鏈式調用,多個操作被組合成一個表達式,這使得代碼更緊湊。
4.?函數式編程 (Functional Programming)
雖然Python不是純粹的函數式編程語言,但這段代碼展示了一些函數式編程的概念,比如:
- 無副作用 (Side-Effect Free):代碼讀取輸入,處理數據,然后輸出結果,沒有修改任何全局狀態。
- 不可變性 (Immutability):split()和[::-1]操作返回新的列表,而不是修改原列表。
5.?內置函數和標準庫的使用 (Leveraging Built-In Functions and Standard Library)
Python的內置函數和標準庫提供了高效且經過優化的實現。通過利用這些函數(如input(), split(), print()),我們可以減少代碼量并提高執行效率。
6.?聲明式編程 (Declarative Programming)
這段代碼更多的是描述了“做什么”,而不是“如何做”。例如,split()描述了要把字符串拆分成單詞,[::-1]描述了要反轉列表,而不是手動實現這些操作。這種聲明式的風格提高了代碼的可讀性和可維護性。
7.?最少驚訝原則 (Principle of Least Astonishment)
代碼的行為符合大多數程序員的預期,沒有復雜的操作和隱藏的副作用。這使得代碼更容易理解和信任。
8.?單一職責原則 (Single Responsibility Principle)
這段代碼的每個部分都只有一個明確的職責:讀取輸入、分割單詞、反轉列表和打印輸出。這符合單一職責原則,使得代碼更模塊化。
9.?組合模式 (Composition over Inheritance)
雖然這段代碼沒有涉及到類和繼承,但它展示了通過組合簡單操作來構建復雜功能的方法。這種組合模式是很多現代編程的核心思想,比繼承更靈活、更易于維護。
總結
這段代碼通過簡潔、高內聚、函數式編程和內置函數的高效使用,展示了許多編程中的重要思想和哲學。這不僅使代碼易于閱讀和維護,也提高了代碼的執行效率。通過這些編程思想的應用,可以編寫出更高質量、更可靠的代碼。
舉一反三
當然,理解這些編程哲學和思想并能在實際編程中靈活應用是非常有價值的。以下是一些具體的技巧和示例代碼,幫助你在編寫代碼時能夠舉一反三。
技巧1:簡潔性 (Simplicity)
技巧:利用Python的內置函數和簡潔語法,使代碼盡可能簡潔。
示例:將一個字符串中的所有數字提取出來,并以列表形式返回。
# 簡潔方式
def extract_digits(s):return [int(char) for char in s if char.isdigit()]# 使用示例
s = "ab12cd34"
print(extract_digits(s)) # 輸出: [1, 2, 3, 4]
技巧2:高內聚 (High Cohesion)
技巧:確保每個函數或代碼塊只做一件事,這有助于代碼的可讀性和可維護性。
示例:將輸入的句子轉換成大寫,并按單詞反轉。
def read_input():return input("Enter a sentence: ")def to_uppercase(s):return s.upper()def reverse_words(s):return ' '.join(s.split()[::-1])def main():sentence = read_input()uppercase_sentence = to_uppercase(sentence)reversed_sentence = reverse_words(uppercase_sentence)print(reversed_sentence)# 使用示例
if __name__ == "__main__":main()
技巧3:面向表達式編程 (Expression-Oriented Programming)
技巧:盡可能使用表達式來進行鏈式操作,使代碼更緊湊。
示例:從一個列表中篩選出所有偶數,并將它們平方后返回。
# 面向表達式編程
def filter_and_square_evens(nums):return [x**2 for x in nums if x % 2 == 0]# 使用示例
nums = [1, 2, 3, 4, 5, 6]
print(filter_and_square_evens(nums)) # 輸出: [4, 16, 36]
技巧4:函數式編程 (Functional Programming)
技巧:盡量避免副作用,使用不可變的數據結構和純函數。
示例:對列表中的每個元素應用一個函數,并返回新的列表。
# 函數式編程
def apply_function(lst, func):return list(map(func, lst))# 使用示例
nums = [1, 2, 3, 4]
print(apply_function(nums, lambda x: x * 2)) # 輸出: [2, 4, 6, 8]
技巧5:聲明式編程 (Declarative Programming)
技巧:更多地描述“做什么”,而不是“如何做”。
示例:從一個字符串中提取所有的單詞,并按字母順序排序。
# 聲明式編程
def extract_and_sort_words(s):return sorted(s.split())# 使用示例
s = "the quick brown fox"
print(extract_and_sort_words(s)) # 輸出: ['brown', 'fox', 'quick', 'the']
技巧6:最少驚訝原則 (Principle of Least Astonishment)
技巧:編寫代碼時,盡量避免復雜和不易理解的邏輯,遵循常見的編程習慣。
示例:創建一個簡單的計算器函數,可以進行加、減、乘、除操作。
# 最少驚訝原則
def calculator(a, b, operation):if operation == 'add':return a + belif operation == 'subtract':return a - belif operation == 'multiply':return a * belif operation == 'divide':if b != 0:return a / belse:return 'Division by zero'else:return 'Unknown operation'# 使用示例
print(calculator(10, 5, 'add')) # 輸出: 15
print(calculator(10, 5, 'divide')) # 輸出: 2.0
技巧7:單一職責原則 (Single Responsibility Principle)
技巧:每個函數或類只負責一項任務。
示例:設計一個簡單的用戶管理系統,每個類和函數都有明確的職責。
class User:def __init__(self, username, email):self.username = usernameself.email = emailclass UserManager:def __init__(self):self.users = []def add_user(self, user):self.users.append(user)def remove_user(self, username):self.users = [user for user in self.users if user.username != username]def get_user(self, username):for user in self.users:if user.username == username:return userreturn None# 使用示例
user1 = User('alice', 'alice@example.com')
user2 = User('bob', 'bob@example.com')manager = UserManager()
manager.add_user(user1)
manager.add_user(user2)print(manager.get_user('alice').email) # 輸出: alice@example.com
manager.remove_user('alice')
print(manager.get_user('alice')) # 輸出: None
技巧8:組合模式 (Composition over Inheritance)
技巧:通過組合簡單功能來構建復雜功能,而不是通過繼承來擴展功能。
示例:實現一個具有加法和乘法功能的計算器,并使用組合方式擴展新的功能。
class Adder:def add(self, a, b):return a + bclass Multiplier:def multiply(self, a, b):return a * bclass Calculator:def __init__(self, adder, multiplier):self.adder = adderself.multiplier = multiplierdef add(self, a, b):return self.adder.add(a, b)def multiply(self, a, b):return self.multiplier.multiply(a, b)# 使用示例
adder = Adder()
multiplier = Multiplier()
calculator = Calculator(adder, multiplier)print(calculator.add(3, 4)) # 輸出: 7
print(calculator.multiply(3, 4)) # 輸出: 12
總結
通過這些技巧和示例代碼,可以更好地理解和應用編程中的重要思想和哲學。這不僅有助于寫出更高效、更易維護的代碼,還能提高編程技能和思維能力。
感謝閱讀。