分享一篇文章惨撇,原文來自https://medium.freecodecamp.org/learning-python-from-zero-to-hero-120ea540b567。國內(nèi)譯文出版應(yīng)當(dāng)來自于https://www.oschina.net/translate/learning-python-from-zero-to-hero平酿。
第一個問題,什么是 Python 悦陋?根據(jù) Python 之父 Guido van Rossum 的話蜈彼,Python 是:
一種高級程序語言,其核心設(shè)計哲學(xué)是代碼可讀性和語法俺驶,能夠讓程序員用很少的代碼來表達自己的想法幸逆。
對于我來說,學(xué)習(xí) Python 的首要原因是暮现,Python 是一種可以優(yōu)雅編程的語言还绘。它能夠簡單自然地寫出代碼和實現(xiàn)我的想法。
另一個原因是我們可以將 Python 用在很多地方:數(shù)據(jù)科學(xué)栖袋、Web 開發(fā)和機器學(xué)習(xí)等都可以使用 Python 來開發(fā)蚕甥。Quora、Pinterest 和 Spotify 都使用 Python 來進行他們的后端 Web 開發(fā)栋荸。那么讓我們來學(xué)習(xí)一下 Python 吧。
Python 基礎(chǔ)
1. 變量
你可以把變量想象成一個用來存儲值的單詞。我們看個例子晌块。
Python 中定義一個變量并為它賦值是很容易的爱沟。假如你想存儲數(shù)字 1 到變量 “one” ,讓我們試試看:
one = 1
超級簡單吧匆背?你只需要把值 1 分配給變量 “one” 呼伸。
two = 2
some_number = 10000
只要你想,你可以把任意的值賦給任何其他的變量钝尸。正如你從上面看到的那樣括享,變量 “two” 存儲整型變量 2 ,變量 “some_number” 存儲 10000 珍促。
除了整型铃辖,我們還可以使用布爾值(True/Flase)、字符串猪叙、浮點型和其他數(shù)據(jù)類型娇斩。
# booleanstrue_boolean = Truefalse_boolean = False# stringmy_name = "Leandro Tk"# floatbook_price = 15.80
2. 控制流程:條件語句
“If” 使用一個表達式來判斷一個語句是 True 還是 False ,如果是 True 穴翩,那么執(zhí)行 if 內(nèi)的代碼犬第,例子如下:
if True:
print("Hello Python If")
if 2 > 1:
print("2 is greater than 1")
2 比 1 大,所以 print 代碼被執(zhí)行芒帕。
當(dāng)“if”里面的表達式是 false 時歉嗓,“else” 語句將會執(zhí)行。
if 1 > 2:
print("1 is greater than 2")
else:
print("1 is not greater than 2")
1 比 2 小背蟆,所以 “else” 里面的代碼會執(zhí)行鉴分。
你也可以使用 “elif” 語句:
if 1 > 2:
print("1 is greater than 2")elif 2 > 1:
print("1 is not greater than 2")else:
print("1 is equal to 2")
3. 循環(huán)和迭代
在 Python 中,我們可以用不同的形式進行迭代淆储。我會說下 while 和 for冠场。
While 循環(huán):當(dāng)語句是 True 時,while 內(nèi)部的代碼塊會執(zhí)行本砰。所以下面這段代碼會打印出 1 到 10 碴裙。
num = 1
while num <= 10:
print(num)
num += 1
while 循環(huán)需要循環(huán)條件,如果條件一直是 True 点额,它將會一直迭代舔株,當(dāng) num 的值為 11 時,循環(huán)條件為 false 还棱。
另一段代碼可以幫你更好的理解 while 語句的用法:
loop_condition = Truewhile loop_condition:
print("Loop Condition keeps: %s" %(loop_condition))
loop_condition = False
循環(huán)條件是 True 所以會一直迭代载慈,直到為 False 。
For 循環(huán):你可以在代碼塊上應(yīng)用變量 “num” 珍手,而 “for” 語句將為你迭代它办铡。此代碼將打印與 while 中相同的代碼:從 1 到 10 辞做。
for i in range(1, 11):
print(i)
瞧見沒?這太簡單了寡具。i 的范圍從 1 開始一直到第 11 個元素(10是第十個元素)
List:集合 | 數(shù)組 | 數(shù)據(jù)結(jié)構(gòu)
假如你想要在一個變量里存儲整數(shù) 1 秤茅,但是你也要存儲 2 和 3 , 4 , 5 ...
不是用成百上千個變量,我有別的方法存儲這些我想要存儲的整數(shù)嗎童叠?你已經(jīng)猜到了框喳,確實有別的存儲它們的方法。
列表是一個集合厦坛,它能夠存儲一列值(就像你想要存儲的這些)五垮,那么讓我們來用一下它:
my_integers = [1, 2, 3, 4, 5]
這真的很簡單。我們創(chuàng)建了一個叫做 my_integer 的數(shù)組并且把數(shù)據(jù)存到了里面杜秸。
也許你會問:“我要怎樣獲取數(shù)組里的值放仗?”
問得好。列表有一個叫做索引的概念亩歹。第一個元素的下表是索引0(0)匙监。第二個的索引是1洋只,以此類推檩小,你應(yīng)該明白的横漏。
為了使它更加簡潔屋休,我們可以用它的索引代表數(shù)組元素命锄。我畫了出來:
用 Python 的語法歧胁,也很好去理解:
my_integers = [5, 7, 1, 3, 4]
print(my_integers[0]) # 5print(my_integers[1]) # 7print(my_integers[4]) # 4
假如你不想存整數(shù)低斋。你只想去存一些字符串俐筋,像你親戚名字的列表静秆。我的看起來是類似這樣的:
relatives_names = [ "Toshiaki", "Juliana", "Yuji", "Bruno", "Kaio"]
print(relatives_names[4]) # Kaio
它的原理跟存整數(shù)一樣粮揉,很友好。
我們只學(xué)習(xí)了列表的索引是如何工作的抚笔,我還需要告訴你如何向列表的數(shù)據(jù)結(jié)構(gòu)中添加一個元素(向列表中添加一個項目)扶认。
最常用的向列表中添加新數(shù)據(jù)的方法是拼接。我們來看一下它是如何使用的:
bookshelf = []
bookshelf.append("The Effective Engineer")
bookshelf.append("The 4 Hour Work Week")
print(bookshelf[0]) # The Effective Engineerprint(bookshelf[1]) # The 4 Hour Work W
拼接超級簡單殊橙,你僅需要把一個元素(比如“有效的機器”)作為拼接參數(shù)辐宾。
好了,關(guān)于列表的知識這些就夠了膨蛮,讓我們來看一下其它的數(shù)據(jù)結(jié)構(gòu)叠纹。
字典:Key-Value 數(shù)據(jù)結(jié)構(gòu)
現(xiàn)在我們知道 List 是有索引的整型數(shù)字集合。但如果我們不像使用整型數(shù)字作為索引呢敞葛?我們可以用其他的一些數(shù)據(jù)結(jié)構(gòu)誉察,比如數(shù)字、字符串或者其他類型的索引惹谐。
讓我們學(xué)習(xí)下字典這種數(shù)據(jù)結(jié)構(gòu)持偏。字典是一個鍵值對的集合驼卖。字典差不多長這樣:
dictionary_example = {
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
Key 是指向 value 的索引。我們?nèi)绾卧L問字典中的 value 呢综液?你應(yīng)該猜到了款慨,那就是使用 key 。我們試一下:
dictionary_tk = {
"name": "Leandro",
"nickname": "Tk",
"nationality": "Brazilian"
}
print("My name is %s" %(dictionary_tk["name"])) # My name is Leandro
print("But you can call me %s" %(dictionary_tk["nickname"])) # But you can call me Tk
print("And by the way I'm %s" %(dictionary_tk["nationality"])) # And by the way I'm Brazilian
我們有個 key(age)value(24)谬莹,使用字符串作為 key 整型作為 value 。
我創(chuàng)建了一個關(guān)于我的字典桩了,其中包含我的名字附帽、昵稱和國籍。這些屬性是字典中的 key 井誉。
就像我們學(xué)過的使用索引訪問 list 一樣蕉扮,我們同樣使用索引(在字典中 key 就是索引)來訪問存儲在字典中的 value 。
正如我們使用 list 那樣颗圣,讓我們學(xué)習(xí)下如何向字典中添加元素喳钟。字典中主要是指向 value 的 key 。當(dāng)我們添加元素的時候同樣如此:
dictionary_tk = {
"name": "Leandro",
"nickname": "Tk",
"nationality": "Brazilian",
"age": 24
}
print("My name is %s" %(dictionary_tk["name"])) # My name is Leandro
print("But you can call me %s" %(dictionary_tk["nickname"])) # But you can call me Tk
print("And by the way I'm %i and %s" %(dictionary_tk["age"], dictionary_tk["nationality"])) # And by the way I'm Brazilian
我們只需要將一個字典中的一個 key 指向一個 value 在岂。沒什么難的奔则,對吧?
迭代:通過數(shù)據(jù)結(jié)構(gòu)進行循環(huán)
跟我們在 Python 基礎(chǔ)中學(xué)習(xí)的一樣蔽午,List 迭代十分簡單易茬。我們 Python 開發(fā)者通常使用 For 循環(huán)。我們試試看:
bookshelf = [
"The Effective Engineer",
"The 4 hours work week",
"Zero to One",
"Lean Startup",
"Hooked"
]
for book in bookshelf:
print(book)
對于在書架上的每本書及老,我們打映槔场(可以做任何操作)到控制臺上。超級簡單和直觀吧骄恶。這就是 Python 的美妙之處食铐。
對于哈希數(shù)據(jù)結(jié)構(gòu),我們同樣可以使用 for 循環(huán)僧鲁,不過我們需要使用 key 來進行虐呻。
dictionary = { "some_key": "some_value" }
for key in dictionary:
print("%s --> %s" %(key, dictionary[key])) # some_key --> some_value
上面是如何在字典中使用 For 循環(huán)的例子。對于字典中的每個 key 悔捶,我們打印出 key 和 key 所對應(yīng)的 value 铃慷。
另一種方式是使用 iteritems 方法。
dictionary = { "some_key": "some_value" }
for key, value in dictionary.items():
print("%s --> %s" %(key, value))# some_key --> some_value
我們命名兩個參數(shù)為 key 和 value 蜕该,但是這不是必要的犁柜。我們可以隨意命名。我們看下:
dictionary_tk = {
"name": "Leandro",
"nickname": "Tk",
"nationality": "Brazilian",
"age": 24
}
for attribute, value in dictionary_tk.items():
print("My %s is %s" %(attribute, value))
# My name is Leandro
# My nickname is Tk
# My nationality is Brazilian
# My age is 24
可以看到我們使用了 attribute 作為字典中 key 的參數(shù)堂淡,這與使用 key 命名具有同樣的效果馋缅。真是太棒了扒腕!
類&對象
一些理論:
對象是對現(xiàn)實世界實體的表示,如汽車萤悴、狗或自行車瘾腰。 這些對象有兩個共同的主要特征:數(shù)據(jù)和行為。
汽車有數(shù)據(jù)覆履,如車輪的數(shù)量蹋盆,車門的數(shù)量和座位的空間,并且它們可以表現(xiàn)出其行為:它們可以加速硝全,停止栖雾,顯示剩余多少燃料,以及許多其他的事情伟众。
我們將數(shù)據(jù)看作是面向?qū)ο缶幊讨械膶傩院托袨椤?又表示為:
數(shù)據(jù)→ 屬性和行為 → 方法
而類是創(chuàng)建單個對象的藍圖析藕。 在現(xiàn)實世界中,我們經(jīng)常發(fā)現(xiàn)許多相同類型的對象凳厢。 比如說汽車账胧。 所有的汽車都有相同的構(gòu)造和模型(都有一個引擎,輪子先紫,門等)治泥。每輛車都是由同一套藍圖構(gòu)造成的,并具有相同的組件泡孩。
Python 面向?qū)ο缶幊棠J剑篛N
Python车摄,作為一種面向?qū)ο缶幊陶Z言,存在這樣的概念:類和對象仑鸥。
一個類是一個藍圖吮播,是對象的模型。
那么眼俊,一個類是一個模型意狠,或者是一種定義屬性和行為的方法(正如我們在理論部分討論的那樣)。舉例來說疮胖,一個車輛類有它自己的屬性來定義這個對象是個什么樣的車輛环戈。一輛車的屬性有輪子數(shù)量,能源類型澎灸,座位容量和最大時速這些院塞。
考慮到這一點,讓我們來看看 Python 的類的語法:
class Vehicle:
pass
上邊的代碼性昭,我們使用 class 語句來定義一個類拦止。是不是很容易?
對象是一個類的實例化,我們可以通過類名來進行實例化汹族。
car = Vehicle()
print(car) # <__main__.Vehicle instance at 0x7fb1de6c2638>
在這里萧求,car 是類 Vehicle 的對象(或者實例化)。
記得車輛類有四個屬性:輪子的數(shù)量顶瞒,油箱類型夸政,座位容量和最大時速。當(dāng)我們新建一個車輛對象時要設(shè)置所有的屬性榴徐。所以在這里守问,我們定義一個類在它初始化的時候接受參數(shù):
class Vehicle:
def __init__(self, number_of_wheels, type_of_tank, seating_capacity, maximum_velocity):
self.number_of_wheels = number_of_wheels
self.type_of_tank = type_of_tank
self.seating_capacity = seating_capacity
self.maximum_velocity = maximum_velocity
這個 init 方法。我們稱之為構(gòu)造函數(shù)坑资。因此當(dāng)我們在創(chuàng)建一個車輛對象時酪碘,可以定義這些屬性。想象一下盐茎,我們喜歡 Tesla Model S ,所以我們想創(chuàng)建一個這種類型的對象徙赢。它有四個輪子字柠,使用電能源,五座并且最大時時速是250千米(155英里)狡赐。我們開始創(chuàng)建這樣一個對象:
tesla_model_s = Vehicle(4, 'electric', 5, 250)
四輪+電能源+五座+最大時速250千米窑业。
所有的屬性已經(jīng)設(shè)置了。但我們該如何訪問這些屬性值呢枕屉?我們給對象發(fā)送消息以向其請求該值常柄。我們稱之為方法。它是對象的行為搀擂。讓我們實現(xiàn)它:
class Vehicle:
def __init__(self, number_of_wheels, type_of_tank, seating_capacity, maximum_velocity):
self.number_of_wheels = number_of_wheels
self.type_of_tank = type_of_tank
self.seating_capacity = seating_capacity
self.maximum_velocity = maximum_velocity def number_of_wheels(self):
return self.number_of_wheels def set_number_of_wheels(self, number):
self.number_of_wheels = number
這是兩個方法number_of_wheels和set_number_of_wheels的實現(xiàn)西潘。我們將其稱為getter & setter。因為第一個函數(shù)是獲取屬性值哨颂,第二個函數(shù)是給屬性設(shè)置新的值喷市。
在 Python 中,我們可以使用@property (修飾符)來定義getters和setters威恼。讓我們看看實際代碼:
class Vehicle:
def __init__(self, number_of_wheels, type_of_tank, seating_capacity, maximum_velocity):
self.number_of_wheels = number_of_wheels
self.type_of_tank = type_of_tank
self.seating_capacity = seating_capacity
self.maximum_velocity = maximum_velocity @property
def number_of_wheels(self):
return self.number_of_wheels @number_of_wheels.setter
def number_of_wheels(self, number):
self.number_of_wheels = number
并且我們可以將這些方法作為屬性使用:
tesla_model_s = Vehicle(4, 'electric', 5, 250)
print(tesla_model_s.number_of_wheels) # 4tesla_model_s.number_of_wheels = 2 # setting number of wheels to 2print(tesla_model_s.number_of_wheels) # 2
這和方法定義有輕微的不同品姓。這里的方法是按照屬性執(zhí)行的。例如當(dāng)我們設(shè)置新的輪胎數(shù)目時箫措,我們并不將這兩個看做參數(shù)腹备,而是將數(shù)值2設(shè)置給number_of_wheels。這是編寫python風(fēng)格的getter和setter代碼的一種方式斤蔓。
但我們也可以將該方法用于其他事項植酥,例如“make_noise”方法。讓我們看看:
class Vehicle:
def __init__(self, number_of_wheels, type_of_tank, seating_capacity, maximum_velocity):
self.number_of_wheels = number_of_wheels
self.type_of_tank = type_of_tank
self.seating_capacity = seating_capacity
self.maximum_velocity = maximum_velocity def make_noise(self):
print('VRUUUUUUUM')
當(dāng)我們調(diào)用此方法時附迷,它僅僅返回一個字符串“VRRRRUUUUM.”
tesla_model_s = Vehicle(4, 'electric', 5, 250)
tesla_model_s.make_noise() # VRUUUUUUUM
封裝: 隱藏信息
封裝是一種限制直接訪問對象數(shù)據(jù)和方法的機制惧互。但與此同時哎媚,它使得在數(shù)據(jù)上操作更簡單(對象的方法)。
“封裝可被用于隱藏數(shù)據(jù)成員和成員函數(shù)喊儡。按照這個定義拨与,封裝意味著 對象的內(nèi)部表示一般在對象定義的外部視圖中隱藏“拢”?—?Wikipedia
對象的所有內(nèi)部表示都對外部隱藏了买喧。只有對象本身可以與其內(nèi)部數(shù)據(jù)交互。
首先匆赃,我們需要理解公開的淤毛、非公開的實例變量和方法的工作原理。
公共實例變量
對于 Python 類算柳,我們可以在我們的構(gòu)造函數(shù)方法中初始化一個公共實例變量低淡。讓我們看看這個:
在這個構(gòu)造方法中:
class Person:
def __init__(self, first_name):
self.first_name = first_name
在這里,我們將 first_name 值作為參數(shù)應(yīng)用于公共實例變量瞬项。
tk = Person('TK')
print(tk.first_name) # => TK
在類中:
class Person:
first_name = 'TK'
在這里蔗蹋,我們不需要將 first_name 作為參數(shù),所有的實例對象都有一個用 TK 初始化的類屬性囱淋。
tk = Person()
print(tk.first_name) # => TK
太酷了猪杭,現(xiàn)在我們已經(jīng)了解到,我們可以使用公共實例變量和類屬性妥衣。關(guān)于公共部分的另一個有趣的事情是我們可以管理變量值皂吮。我的意思是什么呢?我們的對象可以管理它的變量值:Get 和 Set 變量值税手。
還是在 Person 類中蜂筹,我們想為它的 first_name 變量設(shè)置另一個值:
tk = Person('TK')
tk.first_name = 'Kaio'print(tk.first_name) # => Kaio
這就可以了,我們只是為 first_name 實例變量設(shè)置另一個值(kaio)冈止,并更新了值狂票。就這么簡單。因為這是一個公共變量熙暴,我們是可以這么做的闺属。
Non-public 實例變量
這里我們并沒有使用術(shù)語“private”,因為在Python中所有屬性都不是真的私有的(沒有通常不必要的工作量)周霉。?—? PEP 8
作為 public instance variable(公共實例變量)掂器,我們可以在構(gòu)造方法或類內(nèi)部定義 non-public instance variable (非公共實例變量)。語法上的區(qū)別是:對于 non-public instance variables (非公共實例變量)俱箱,在變量名前使用下劃線(_)国瓮。
“除了從對象內(nèi)部外無法被訪問的‘Private’實例變量在Python中并不存在。然而,這里有一個多數(shù)Python代碼都會遵守的慣例:使用下劃線作為前綴的命名(例如 _spam)應(yīng)該被認為是API的非公開部分(不管是函數(shù)乃摹、方法還是數(shù)據(jù)成員)”?—? Python軟件基礎(chǔ)
這里是示例代碼:
class Person:
def __init__(self, first_name, email):
self.first_name = first_name
self._email = email
你看到了email變量了嗎禁漓?這就是我們?nèi)绾味x非公共變量的方法:
tk = Person('TK', 'tk@mail.com')
print(tk._email) # tk@mail.com
我們可以訪問并更新它。非公共變量僅僅是一個慣用法孵睬,并且應(yīng)該被當(dāng)做API的非公共部分播歼。
所以我們使用一個在類定義內(nèi)部的方法來實現(xiàn)該功能。讓我們實現(xiàn)兩個方法(email 和update_email)以加深理解:
class Person:
def __init__(self, first_name, email):
self.first_name = first_name
self._email = email def update_email(self, new_email):
self._email = new_email def email(self):
return self._email
現(xiàn)在我們可以使用這兩個方法來更新及訪問非公開變量了掰读。示例如下:
tk = Person('TK', 'tk@mail.com')
print(tk.email()) # => tk@mail.comtk._email = 'new_tk@mail.com'print(tk.email()) # => tk@mail.comtk.update_email('new_tk@mail.com')
print(tk.email()) # => new_tk@mail.com
- 我們使用first_name TK和email tk@mail.com初始化了一個新對象
- 使用方法訪問非公開變量email并輸出它
- 嘗試在類外部設(shè)置一個新的email
- 我們需要將非公開變量視為API的非公開部分
- 使用我們的實例方法來更新非公開變量
- 成功秘狞!我們使用輔助方法在類內(nèi)部更新了它。
公共方法
對于公共方法蹈集,我們也可以在類中使用它們:
class Person:
def __init__(self, first_name, age):
self.first_name = first_name
self._age = age def show_age(self):
return self._age
讓我們來測試一下:
tk = Person('TK', 25)
print(tk.show_age()) # => 25
很好 - 我們在類中使用它沒有任何問題烁试。
非公共方法
但是用非公開的方法,我們無法做到這一點拢肆。 如果我們想實現(xiàn)相同的 Person 類减响,現(xiàn)在使用有下劃線(_)的 show_age 非公共方法。
class Person:
def __init__(self, first_name, age):
self.first_name = first_name
self._age = age def _show_age(self):
return self._age
現(xiàn)在郭怪,我們將嘗試用我們的對象來調(diào)用這個非公共的方法:
tk = Person('TK', 25)
print(tk._show_age()) # => 25
我們可以訪問和更新它辩蛋。 非公共的方法只是一個慣例,應(yīng)該被視為API的非公開部分移盆。
以下是我們?nèi)绾问褂盟囊粋€例子:
class Person:
def __init__(self, first_name, age):
self.first_name = first_name
self._age = age def show_age(self):
return self._get_age() def _get_age(self):
return self._age
tk = Person('TK', 25)
print(tk.show_age()) # => 25
這里有一個 _get_age 非公共方法和一個 show_age 公共方法。 show_age 可以被我們的對象(不在我們的類中)使用伤为,而 _get_age 只用在我們的類定義里面使用(在 show_age 方法里面)咒循。 但是同樣的,這樣的做法通常是慣例绞愚。
封裝小結(jié)
通過封裝叙甸,我們可以確保對象的內(nèi)部表示是對外部隱藏的。
繼承:行為和特征
某些物體有一些共同之處:它們的行為和特征位衩。
例如裆蒸,我繼承了我父親的一些特征和行為。我繼承了他的眼睛和頭發(fā)的特征糖驴,以及他的急躁和內(nèi)向的行為僚祷。
在面向?qū)ο缶幊讨校惪梢岳^承另一個類的共同特征(數(shù)據(jù))和行為(方法)贮缕。
我們來看另一個例子辙谜,并用 Python 實現(xiàn)它。
想象一下汽車感昼。車輪數(shù)量装哆,座位容量和最大速度都是一輛車的屬性。我們可以說 ElectricCar 類從普通的 Car 類繼承了這些相同的屬性。
class Car:
def __init__(self, number_of_wheels, seating_capacity, maximum_velocity):
self.number_of_wheels = number_of_wheels
self.seating_capacity = seating_capacity
self.maximum_velocity = maximum_velocity
我們 Car 類的實現(xiàn):
my_car = Car(4, 5, 250)
print(my_car.number_of_wheels)
print(my_car.seating_capacity)
print(my_car.maximum_velocity)
一旦初始化蜕琴,我們就可以使用所有創(chuàng)建的實例變量萍桌。太棒了。
在 Python 中凌简,我們將父類作為子的參數(shù)來進行繼承上炎。 ElectricCar 類可以繼承我們的 Car 類。
class ElectricCar(Car):
def __init__(self, number_of_wheels, seating_capacity, maximum_velocity):
Car.__init__(self, number_of_wheels, seating_capacity, maximum_velocity)
就這么簡單号醉。我們不需要實現(xiàn)任何其他方法反症,因為這個類已經(jīng)完成了父類的繼承(繼承自 Car 類)。我們來證明一下:
my_electric_car = ElectricCar(4, 5, 250)
print(my_electric_car.number_of_wheels) # => 4
print(my_electric_car.seating_capacity) # => 5
print(my_electric_car.maximum_velocity) # => 250
干的漂亮畔派。