很早就聽說python的赫赫大名了,這學期學校也開了這門課,正好可以感受一下這門語言的魅力,對比C/C++/JAVA,它到底有什麼獨特的地方呢?
"Life is short, you need Python" --Bruce Eckel
人生苦短,我用python
一. 初印象:short
曾經有這樣一個段子,說聯合國同樣一份檔案,用五大官方語言寫的不同版本中,最薄的那份一定是漢語的。
這個段子放在python身上同樣也成立,幾大主流語言寫同樣一個功能,python的代碼量一定是最短的那個。
比如同樣是hello world
C/C++需要五行:
#include <stdio.h>
int main() {
printf("Hello, World!");
return 0;
}
java也需要五行,但代碼量明顯比上面的要多:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
再看看java的“小弟”javascript:
<html>
<head>
<title>第一個JavaScript程序</title>
</head>
<bdoy>
<script type="text/javascript">
document.write("Hello World!"); // 輸出語句
</script>
</body>
</html>
php:
<html>
<head>
<title>PHP 測試</title>
</head>
<body>
<?php
echo '<p>Hello World</p>'; ?>
</body>
</html>
js和php排除必要的html標籤,也需要一兩行,再看看python:
print("Hello World")
只需要一行,簡單到沒朋友,難怪連小學生都可以輕易上手
這只是python代碼簡短的冰山一角,它幾乎每一部分都是圍繞"short"
來設計的
二、靈活
即使只看列表這一節,也能感受到python的語法是相當靈活的
1. 使用列表推導式
生成列表
#生成含0到9的列表
list = [ x for x in range(10)]
#[0,1,2,3,4,5,6,7,8,9]
#生成指定列表中平方大於200的數的列表
list = [10, 20, 30, 40, 50, 60]
result = [x for x in list if x * x > 200]
#[20, 30, 40, 50, 60]
列表推導式可以看成是for循環的一種簡寫
,使得生成列表的過程變得十分簡單。
2. 使用切片操作列表
舉個簡單的例子:
list = [x for x in range(10)]
#list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#從list中下標0開始,到下標8結束,間隔爲2取列表中的元素
result = list[0:8:2]
#result = [0, 2, 4, 6]
事實上,切片的功能遠非如此,列表的增刪改查都可以通過切片實現
#逆置
result = list[::-1]
#刪除列表下標爲0,1,2的元素
list[:3] = []
#將列表偶數位賦值爲0
list[::2] = [0] * (len(list)//2)
切片更多的操作這裏就不再贅述,總之這個操作十分靈活
,但有時卻不能一眼看出操作實際目的,可讀性低
4. 解包壓包,讓代碼效率如此之高
序列解包,最簡單的理解就是將列表,集合等序列裏的元素剝離出來,而壓包則是相反的過程
最簡單的解包:
x, y, z = [1, 2, 3]
#x = 1, y = 2, z = 3
利用這個功能就可以非常簡便地實現交換
x, y, z = z, x, y
# x = 3, y = 1, z = 2
也可以替代切片操作(表示多個元素,_表示忽略元素,_表示忽略多個元素)
x, *y, z = [1, 2, 3, 4, 5]
# x = 1
# y = [2, 3, 4]
# z = 5
x, *_, z = [1, 2, 3, 4, 5]
# x = 1
# z = 5
還可以在函數中返回多個值:
def testFun(name, number):
return 'name:' + name, 'age:' + number
name, number = testFun('zhangsan', '24')
print(name, number)
# name:zhangsan age:24
最簡單的壓包:
key = ['name', 'age', 'number']
value = ['zhangsan', 12, 1000]
person = dict(zip(key, value))
#person = {'name': 'zhangsan', 'age': 12, 'number': 1000}
解包與壓包混用:
data = [
('Bob', '1990-1-1', 60),
('Mary', '1996-1-4', 50),
('Nancy', '1993-3-1', 55)
]
for name, *args in data:
print(name, args)
# Bob ['1990-1-1', 60]
# Mary ['1996-1-4', 50]
# Nancy ['1993-3-1', 55]
在函數當中使用(可變參數)與*(關鍵字參數,將實參解釋爲鍵值對):
def myfun(first, *middle, last, ** keyAndValue):
print('first = ', first)
print('middle = ', middle)
print('last = ', last)
print('keyAndValue = ', keyAndValue)
myfun(1,2,3, last = 4, name = 'zhangsan', age = 1)
# first = 1
# middle = (2, 3)
# last = 4
# keyAndValue = {'name': 'zhangsan', 'age': 1}
利用*
與**
混用表示任意參數,例如在裝飾器模式中:
def mydecorator(func):
def wrapper(*args, **kw):
print('一個裝飾器')
return func(*args, **kw)
return wrapper
@mydecorator
def myfun(name, age, number):
print(name, age, number)
myfun('zhangsan', 24, 1000)
wrapper函數使用args, *kw作爲參數,則被修飾的myfun函數需要的參數無論是什麼樣的,傳入wrapper都不會報錯,這保證了裝飾器可以修飾各種各樣函數的靈活性。
總結
python剛入門,確實被它簡潔的語法給深深吸引了,甚至一度懷疑自己是在敲指令,而非寫代碼,但它的靈活多變的特性也使得程序在我寫完沒過幾天,就完全看不懂了,即使是一個逗號,冒號也會隱藏大量細節,而這樣的細節通常很難debug出來。代碼太過簡潔,有利也有弊。