本文为 AI 研习社编译的技术博客,原标题 :
Learning Python: From Zero to Hero
翻译 | 永恒如新的日常 校对 | 酱番梨 整理 | 菠萝妹
原文链接:
https://medium.freecodecamp.org/learning-python-from-zero-to-hero-120ea540b567
首先,Python是什么?据它的创始人Guido van Rossum而言,
“Python是一种高级编程语言,它的核心设计思想是代码可读性和允许程序员用几行代码来表达观点的语法。”
就我而言,学习Python的首要理由是,它事实上是一种优雅的编程语言,我可以很自然地进行编程和表达想法。
另一个原因就是在许多方面都可以用它来编程:数据科学、web开发以及机器学习都会通过它而大放光彩。Quora, Pinterest and Spotify都用它来做后台web开发。那么让我们一起来了解一下吧!
1.变量
你可以把变量当成存储值的字符,就是这么简单。
Python中可以很容易地定义变量并对其进行赋值。假如你想把数字1存入一个名为“one”的变量中。让我们一起来做吧:
one = 1
这到底有多简单呢?你只需要把值1赋给变量“one”。
two = 2
some_number = 10000
而且你可以将其它任何值赋给其它任何变量。正如上表中你看到的那样,变量“two”存储整数2,“some_number”存储10000。
除了整型,我们也可以使用布尔型(真/假)、字符串型、浮点型以及其它数据类型。
2.控制流:条件语句
“If”是一种判断语句真假的表达。若为真,就执行“if”内部语句。比如:
if True: print("Hello Python If")
if 2 > 1: print("2 is greater than 1")
2比1大,因此就执行“print”代码。
如果“if”语句为假就会执行“else”语句。
if 1 > 2:
print("1 is greater than 2")
else:
print("1 is not greater than 2")
1不大于2,因此就会执行“else”内部语句。
你也可以使用“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.循环/迭代
Python中有多重循环方法,我会提及两种:while和for。
while循环:当语句为真时,将会执行内部的代码块。因此代码将会输出1到10.
num = 1
while num <= 10:
print(num)
num += 1
while循环需要“循环条件”,若它为真就会执行循环。在本例中,当
数字为11时,循环条件为假。
另一种基本代码更容易理解:
loop_condition = True
while loop_condition:
print("Loop Condition keeps: %s" %(loop_condition))
loop_condition = False
循环条件为真就执行循环直到循环条件置为假为止。
for循环:在块内你可以使用“num”,而且“for”语句也会执行循环。这段代码与while代码(从1到10)的输出是一样的。
for i in range(1, 11):
print(i)
理解?很简单。从1开始进行直到11,10是第十个元素。
假如你想将整数1用一个变量存储,但是现在你或许还想存2、3、4、5以及更多。
我有其它方法来存储我想存的所有整数而不是百万个变量吗?你猜到了——事实上有另一种存储方法。
列表
是可以用来存储一系列值(就像你想存的这些整数)的集合。那么一起来用一下吧:
my_integers = [1, 2, 3, 4, 5]
真的很简单。我们构造一个数组,并将它存在my_integer。
但是或许你会问:“我怎样得到这个数组中的值?”问的好!
列表中有一个索引的概念。第一个元素的索引为0.第二个为1,以此类推,你就明白了。
为了更清楚地表示,我们可以用索引来表示数组和每个元素。我可以画一下:
对于Python语言的使用也很容易理解:
my_integers = [5, 7, 1, 3, 4]
print(my_integers[0]) # 5
print(my_integers[1]) # 7
print(my_integers[4]) # 4
假如你不想存储整数,你想存储字符串,像你的亲人名字的集合。我的看起来是这样的:
relatives_names = [
"Toshiaki",
"Juliana",
"Yuji",
"Bruno",
"Kaio"
]
print(relatives_names[4]) # Kaio
它和整型的操作方式一样。真棒!
我们只是学习索引如何有效使用,但是我仍然需要告诉你我们如何将一个元素加入数据结构(向列表中加入一项)。
向列表中增加一个新值最常见的方法就是append,让我们一起来看看它是如何进行的:
bookshelf = []
bookshelf.append("The Effective Engineer")
bookshelf.append("The 4 Hour Work Week")
print(bookshelf[0]) # The Effective Engineer
print(bookshelf[1]) # The 4 Hour Work Week
append超级简单。你只需要将这个元素当作参数使用就行(有效的工程师)。这部分足够了。让我们谈论下一种数据结构吧。
现在我们都知道,列表以整数作为索引,但是我们不想用整数作为索引怎么办?我们可以使用的数据结构有数值型、字符串型或者是其它索引类型。
让我们一起来了解一下字典这种数据结构吧。
dictionary_example = {
"key1": "value1",
"key2": "value2",
"key3": "value3"}
字典是键值对的集合,值的索引指向键。我们如何获取字典中的值呢?你猜对了——使用键。让我们一起来试一下:
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
我构造了一个有关于我的字典,包括我的姓名、昵称和国籍。这些属性都是字典的键。正如我们学过的如何使用索引来获取列表一样,我们也使用索引来得到存储在字典中的值。比如,我输出一句有关我的语句,而它会用到所有存储在字典中的属性。非常简单,对吗?还有一件很赞的事,我们可以把任何东西当作值来使用。在我所构造的字典中,我想增加一个键“年龄”,而且我的真正的整数年龄也在里面:
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
这里,我们有一组键(年龄)值(24)对,其中键为字符串型,值为整型。和我们用列表做的一样,让我们学一下如何向字典中增加元素吧。字典中很大一部分都是键指向值。当我们谈论向字典中增加元素的时候,
dictionary_tk = {
"name": "Leandro",
"nickname": "Tk",
"nationality": "Brazilian"
}
dictionary_tk['age'] = 24
print(dictionary_tk) # {'nationality': 'Brazilian', 'age': 24, 'nickname': 'Tk', 'name': 'Leandro'}
我们只需要给字典中的键赋一个值。这里没有什么是复杂的,对吗?
正如我们在Python基础部分学习的那样,列表循环很简单。Python开发者一般都是用for循环。让我们做一下吧:
bookshelf = [
"The Effective Engineer",
"The 4 hours work week",
"Zero to One",
"Lean Startup",
"Hooked"
]
for book in bookshelf:
print(book)
对于书架上的每本书,我们(可以用它做任何事)将它打印出来。非常简单直观,这就是Python。
对于一个哈希数据结构,我们同样可以使用for循环,但是我们要运用键。
dictionary = { "some_key": "some_value" }
for key in dictionary:
print("%s --> %s" %(key, dictionary[key])) # some_key --> some_value
这是一个如何使用的例子。对于字典中的每个键,我们都会输出键和与之对应的值。另一种方法是用iteritems方法。我们的确命名两个参数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
我们可以把我们使用的属性看作是字典key的一个参数,而且它可以正常运行。好极了!
一点点理论
对象表示真实世界中的实体,像汽车、小狗或自行车。对象共享两个主要特性:数据和行为。
汽车有数据,比如车轮数、车门数以及座位容量。它们也有可显示的行为:加速、停车、显示剩余燃料以及其它事情。
在面向对象过程中,我们把数据当作属性,把行为当作方法。再来一次,数据——>属性,行为——>方法。而且从所构造的个体对象来看,类是模型。在现实生活中,我们经常会发现许多相同类型的实体,比如汽车。模型和形状都是一样的(而且都有发动机、车轮、车门等等)每辆车都用相同的模型和组件。
Python作为一种面向对象的编程语言,有类和对象的概念。类是对象的模型。类只是一个模型,或者说是一种定义属性和行为的方法(正如我们在理论部分所谈到的那样)。举个例子,一个车辆类有自己的属性,用于定义那些对象是车辆。车轮数、油箱类型、座位数和最快速度都是一辆车的属性。带着这些,让我们一起来看看Python中类的语法:
class Vehicle:
pass
我们通过类声明来定义类——就是这样,很简单吧!对象是类的一个实例。我们通过命名类来构造一个实例。
car = Vehicle()
print(car) # <__main__.Vehicle instance at 0x7fb1de6c2638>
这里的car就是一个类Vehicle的一个对象(或实例)。记得我们的车辆类有四个属性:车轮数、油箱类型、座位数和最快速度。当我们构造一个车辆对象时就需要设置这些属性。因此这里,我们需要定义我们的类,当它初始化的时候能够接收数据。
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方法。我们称它为构造方法。因此当我们构造一个车辆实体时,我们可以定义这些属性。假设我们都喜欢特斯拉模型S,我们想要构造一个这种类型的对象。它是电动的,有四个车轮和五个座位,而且最快速度为250千米/小时(155英里/小时)。让我们创建一个这种对象:
tesla_model_s = Vehicle(4, 'electric', 5, 250)
对所有属性进行设置:四个轮子+电动“油箱类型”+五个座位+最快速度为250千米/小时。但是我们如何获取这些属性的值呢?我们向该对象发送了一条查询属性值的信息,我们称之为方法,它是对象的行为。让我们一起来实现吧:
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
包括两种方法的实现:车轮数和车轮数的设置。我们称为getter和setter,因为前者获得属性值,而后者获得该属性的一个新值。
在Python中,我们可以这样做:用@property(decorators)来定义getter和setter。来看一下代码:
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) # 4
tesla_model_s.number_of_wheels = 2 # setting number of wheels to 2
print(tesla_model_s.number_of_wheels) # 2
这里有点不同于定义方法,方法和属性的作用一样。比如,当我们设置新的车轮数时,我们不会把2作为参数,而是把number_of_wheels的值设为2。这是一种getter和setter方法的代码形式。但是对于其他的我们也可以用一些方法,比如“制造噪音”方法。让我们一起来看一下:
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')
当我们调用这种方法时,它就会返回一串“VRRRRUUUUM”。
tesla_model_s = Vehicle(4, 'electric', 5, 250)
tesla_model_s.make_noise() # VRUUUUUUUM
封装机制不允许直接获取对象的数据和方法,但与此同时,它提供了对数据和方法的操作。
“封装可以用来隐藏数据成员和功能成员,在此定义下,封装意味着一个对象的内部表示通常对该对象以外是隐藏的”。——维基百科
一个对象的内部表示对外界是隐藏的,只有该对象可以联系到其内部数据。首先我们需要理解公有和非公有实例变量和方法如何运行。
对于一个Python类,我们用结构化方法初始化一个公有实例变量,让我们一起来看一下:
class Person:
def __init__(self, first_name):
self.first_name = first_name
在结构体方法中,我们用first_name的值作为对公有实例变量的声明。
tk = Person('TK')
print(tk.first_name) # => TK
在类中,我们不需要将first_name作为声明,而且实例对象会有一个类属性,并用初始化为TK。
tk = Person()
print(tk.first_name) # => TK
很棒!现在我们知道我们可以使用公有实例变量和类属性。另一件有关于公有部分的有趣的事情是我们可以管理变量的值。那意味着什么?对象可以管理和设置其变量的值。
要记得Person类,我们想给它的first_name设置另一个值:
tk = Person('TK')
tk.first_name = 'Kaio'
print(tk.first_name) # => Kaio
开始了,我们只是把kaio赋给first_name这个实例变量,而且对其值进行了更新。很简单,因为它是公有变量,所以我们可以这样做。
这里我们不用“私有”这一术语,因为在Python中不存在真正的私有属性(一般没有不必要的工作量)。——PEP 8
正如public instance variable一样,我们可以用构造方法或在类内定义non-public instance variable。语法上的不同有:non-public instance variables在变量名前使用下划线。
“在Python中不存在这样的情况:在对象内部以外无法获取‘private’实例变量,然而在Python代码中一贯遵循的一个习惯是:变量名前要加下划线前缀(比如:_spam),名字一般作为API的非公有部分(无论它是函数、方法还是数据成员)”——Python Software Foundation
有这样一个例子:
class Person:
def __init__(self, first_name, email):
self.first_name = first_name
self._email = email
你看到email变量了吗?它显示了我们如何定义non-public variable:
tk = Person('TK', 'tk@mail.com')
print(tk._email) # tk@mail.com
我们可以获得并更新它。Non-public variables仅仅是种习惯,而且应该被当作API的非公有部分。因此我们用一种方法,它允许我们在类内对其进行定义。一起来实现以下两个方法: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
现在我们使用方法可以更新和获取non-public variables。让我们一起来看一下:
tk = Person('TK', 'tk@mail.com')
print(tk.email()) # => tk@mail.com
tk._email = 'new_tk@mail.com'
print(tk.email()) # => tk@mail.com
tk.update_email('new_tk@mail.com')
print(tk.email()) # => new_tk@mail.com
1.我们用TK和tk@mail.com对一个新对象的first_name和email进行初始化。
2.使用方法获得non-public variable,然后输出email。
3.试着在我们的类外设置一个新的email。
4.我们需要将non-public variable作为API的non-public部分。
5.用我们的实例方法更新non-public variable。
6.成功了!我们借助帮助方法可以在类内对其进行更新。
我们可以在类外使用公有方法
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
棒极了——没有任何问题!
对于非公有方法,我们不能那样做。一起来实现一个同样的Person类,但是现在我们会用下划线表示non-public method,即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
现在会通过对象来调用这个方法:
tk = Person('TK', 25)
print(tk._show_age()) # => 25
我们可以获得它并对其进行更新。Non-public methods仅仅只是个习惯,而且应该当作API的非公有部分。这里有个例子是有关于对它的使用:
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
这里我们有一个public method为show_age,我们的对象(在类外)可以使用它,而_get_age只能在类定义部分使用(在show_age方法中)。再次提醒:这只是习惯问题。
有了封装,我们可以确保对象的内部表示对外是隐藏的。
某些对象有共同点:行为和特性
举个例子,我继承了我父亲的一些行为和特性。我继承了他的眼睛和头发作为特性,他的不耐心和内向作为行为。
在面向对象编程中,类可以继承另一个类的共同特性(数据)和行为(方法)。
让我们一起来看另一个例子,并用Python对其进行实现。
假定有一辆汽车,它的属性有:车轮数、座位数和最快速度。我们可以说电动车类继承普通车类的这些相同属性。
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
已经实现了我们的汽车类:
my_car = Car(4, 5, 250)
print(my_car.number_of_wheels)
print(my_car.seating_capacity)
print(my_car.maximum_velocity)
一旦对其进行初始化,我们就可以使用所构造的所有instance variables。非常棒!在Python中,我们可以将parent class作为child class的一个参数。一个电动车类可以继承我们的汽车类。
class ElectricCar(Car):
def __init__(self, number_of_wheels, seating_capacity, maximum_velocity):
Car.__init__(self, number_of_wheels, seating_capacity, maximum_velocity)
就是这么简单。我们不需要实现其它任何方法,因为这个类已经有了这些方法(继承了汽车类)。让我们来证明一下:
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
非常漂亮!
有关Python基础,我们已经学了很多:
Python的变量如何工作
Python条件声明如何实现
Python循环如何实现
如何使用List:Collection|Array
字典键值对集合
如何利用这些数据结构实现循环
对象和类
属性作为对象的数据
方法作为对象的行为
使用Python的getters和setters和property装饰器
封装:隐藏信息
继承:行为和特性
祝贺你!你已经完成了有关Python的难理解的部分。
如果你想学习完整的Python课程,学习更多的编程技巧和项目搭建,建议试一下One Month Python Bootcamp部分
有关我的日志学习和编程掌握的更多故事和帖子,可以关注我所发布的The Renaissance Developer。
玩的开心,继续学习并保持编程!
我的Instagram,Twitter,GithubLinkdle。
想要继续查看该篇文章相关链接和参考文献?
戳链接:
http://www.gair.link/page/TextTranslation/830
AI研习社每日更新精彩内容,点击文末【阅读原文】即可观看更多精彩内容:
良心推荐:一份 20 周学习计算机科学的经验贴(附资源)
多目标追踪器:用OpenCV实现多目标追踪(C++/Python)
为计算机视觉生成大的、合成的、带标注的、逼真的数据集
悼念保罗·艾伦,除了他科技圈还有哪些大佬值得信仰?
等你来译:
自动文本提取
用 4 种卷积神经网络,轻松分类时尚图像
使用 SKIL 和 YOLO 构建产品级目标检测系统
很有启发性的25个开源机器学习项目
号外号外~
想要获取更多AI领域相关学习资源,可以访问AI研习社资源板块下载,
所有资源目前一律限时免费,欢迎大家前往社区资源中心
(http://www.gair.link/page/resources)下载喔~