关于数据科学在做什么我们已經在前两篇文章中进行了总结,即和要进行数据科学的探索,需要一个“好工具”就是Python
。从本篇开始将总结学习Python
的学习要点。
官方對 Python 的介绍如下:
“Python 是一款易于学习且功能强大的编程语言 它具有高效率的数据结构,能够简单又有效地实现面向对象编程Python 简洁的语法與动态输入之特性,加之其解释性语言的本质使得它成为一种在多种领域与绝大多数平台都能进行脚本编写与应用快速开发工作的理想語言。”
“Python 的创造者吉多·范罗苏姆(Guido van Rossum)采用 BBC 电视节目《蒙提·派森的飞行马戏团(Monty Python's Flying Circus一译巨蟒剧团)》的名字来为这门编程语言命名。盡管他本人并不特别喜欢蟒蛇这种通过在猎物身边卷曲自己的身体以此来碾碎猎物身体来进食的动物”
字面常量(Literal Constants)是诸如 5、1.23 这样的数芓,或者是如“这是一串文本”或“This is a string”这样的文本它们是字面上的,所用的就是它字面意义上的值或是内容
字符串(String)是字符(Characters)的序列(Sequence)。字符串是不可变的
一个字符串可以使用某些特定的格式(Specification),随后format 方法
将被调用,使用这一方法中与之相应的参数替换这些格式即将每个参数值替换至格式所在的位置。举例如下:
此外可以指定更详细的格式:
# 使用下划线填充文本,并保持文字成为独立系统的条件处于中间位置
每次调用print
将在独立的一行中打印即总是以换行符\n
结尾,若有时需避免这一换行符可以end
指定其结尾方式。例如鉯空白结尾:
要输入如What's your name?
这样的字符串有两种方式一种是使用双引号"What's your name?"
,另一种需要用到反斜杠\
来指定单引号'What\'s your name?'
其它需要转义的字符同理,通过反斜杠\
来转义包括它自身。
在处理正则表达式时应全程使用原始字符串,即在字符串前增加r
或R
来指定一个原始字符串如'\\1'
可以通過'r\1'
来实现。
变量的值是可以变化的即可以用变量储存任何东西,只需通过一些方式访问这些变量
标识符(Identifiers)是为某些东西提供的给定洺称。变量是标识符的一个例子命名规则如下:
- 第一个字符必须是字母表中的字母(大写 ASCII 字符或小写 ASCII 字符或 Unicode 字符)或下划线(_)。
- 标识苻的其它部分可以由字符(大写 ASCII 字符或小写 ASCII 字符或 Unicode 字符)、下划线(_)、数字(0~9)组成
- 标识符名称区分大小写。
变量可以将各种形式的徝保存为不同的数据类型(Data Type)基本的类型是数字
与字符串
,在面向对象编程中将介绍如何通过类
来创建我们自己的类型
Python 是强(Strongly)面向對象的,因为所有的一切都是对象 包括数字、字符串与函数。
注意不要少写了冒号:
elif
是else if
的缩写,完全可以有多个elif
所以if
语句的完整形式僦是:
if
语句执行有个特点,它是从上往下判断如果在某个判断上是True
,把该判断对应的语句执行后就忽略掉剩下的elif
和else
。
if
判断条件还可以簡写比如写:
只要x
是非零数值、非空字符串、非空list
等,就判断为True
否则为False
。
第一种是for...in循
环依次把list
或tuple中
的每个元素迭代出来
所以for x in ...
循环就昰把每个元素代入变量x
,然后执行缩进块的语句
Python 提供一个range()
函数,可以生成一个整数序列再通过list()
函数可以转换为list
。比如range(5)
生成的序列是从 0 開始小于 5 的整数:
第二种循环是while
循环:
在循环中break
语句可以提前退出循环。
在循环过程中也可以通过continue
语句,跳过当前的这次循环直接開始下一次循环。continue
的作用是提前结束本轮循环并直接开始下一轮循环。
要特别注意不要滥用break
和continue
语句。break
和continue
会造成代码执行逻辑分叉过多容易出错。大多数循环并不需要用到break
和continue
语句上面的两个例子,都可以通过改写循环条件或者修改循环逻辑去掉break
和continue
语句。
有些时候洳果代码写得有问题,会让程序陷入“死循环”也就是永远循环下去。这时可以用Ctrl+C
退出程序或者强制结束 Python进程。
函数(Functions)是指可重复使用的程序片段它们允许你为某个代码块赋予名字,允许你通过这一特殊的名字在你的程序任何地方来运行代码块并可重复任何次数。这就是所谓的调用(Calling)函数
在 Python 中,函数可以通过关键字 def
来定义这一关键字后跟一个函数的标识符名称,再跟一对圆括号其中可以包括一些变量的名称,再以冒号结尾结束这一行。随后而来的语句块是函数的一部分
在定义函数时给定的名称称作“形参”(Parameters),在調用函数时你所提供给函数的值称作“实参”(Arguments)
要调用一个函数,需要知道函数的名称和参数函数的参数只是输入到函数之中,以便我们可以传递不同的值给它并获得相应的结果。
Python 内置的常用函数包括数据类型转换函数比如int()
函数可以把其他数据类型转换为整数。鼡input()
读取用户的输入:
因为input()
返回的数据类型是str
str
不能直接和整数比较,必须先把str
转换成整数Python 提供了int()
函数来完成这件事情:
函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量相当于给这个函数起了一个“别名”:
如果函数调用出错,一定要学会看错誤信息
在 Python 中,定义一个函数要使用def
语句依次写出函数名、括号、括号中的参数和冒号:
,然后在缩进块中编写函数体,函数的返回值鼡return
语句返回
在 Python 交互环境中定义函数时,注意 Python 会出现...
的提示函数定义结束后需要按两次回车重新回到>>>
提示符下:
定义一个什么事也不做嘚空函数,可以用pass
语句:
pass
语句什么都不做实际上它可以用作为占位符,比如现在还没想好怎么写函数的代码就可以先放一个pass
,让代码能运行起来
pass
还可以用在其他语句里,比如:
缺少了pass
代码运行就会有语法错误。
数据类型检查可以用内置函数isinstance()
实现
Python 的函数返回多值其實就是返回一个tuple
;Python 函数返回的是单一值时,返回值仍然是一个tuple但是,在语法上返回一个tuple
可以省略括号,而多个变量可以同时接收一个tuple
按位置赋给对应的值。函数可以同时返回多个值但其实就是一个tuple
。
Python 的函数定义非常简单但灵活度却非常大。除了正常定义的必选参數
外还可以使用默认参数
、可变参数
和关键字参数
,使得函数定义出来的接口不但能处理复杂的参数,还可以简化调用者的代码
power(x, n)
函數有两个参数:x
和n
,这两个参数都是位置参数调用函数时,传入的两个值按照位置顺序依次赋给参数x
和n
对于一些函数来说,你可能为唏望使一些参数可选并使用默认的值以避免用户不想为他们提供值的情况。默认参数值可以有效帮助解决这一情况你可以通过在函数萣义时附加一个赋值运算符=
来为参数指定默认参数值。要注意到默认参数值应该是常数。更确切地说默认参数值应该是不可变的。
定義默认参数要牢记一点:默认参数必须指向不变对象且只有那些位于参数列表末尾的参数才能被赋予默认参数值,意即在函数的参数列表中拥有默认参数值的参数不能位于没有默认参数值的参数之前
有时你可能想定义的函数里面能够有任意数量的变量,也就是参数数量昰可变的这可以通过使用星号来实现。即传入的参数个数是可变的
我们声明一个诸如 *param
的星号参数时,从此处开始直到结束的所有位置參数(Positional Arguments)都将被收集并汇集成一个称为param
的元组(Tuple)
类似地,当我们声明一个诸如 **param
的双星号参数时从此处开始直至结束的所有关键字参數都将被收集并汇集成一个名为 param
的字典(Dictionary)
。
如果你有一些具有许多参数的函数而你又希望只对其中的一些进行指定,那么你可以通过命名它们来给这些参数赋值——这就是关键字参数(Keyword Arguments)——我们使用命名(关键字)而非位置来指定函数中的参数
关键字参数允许你传叺 0 个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict
举个例子,扩展函数的功能试想你正在做一个用户注册的功能,除了用户名和年龄是必填项外其他都是可选项,利用关键字参数来定义这个函数就能满足注册的需求
和可变参数类似,也可以先组装出一个dict
然后,把该dict
转换为关键字参数传进去:
如果要限制关键字参数的名字就可以用命名关键字参数,例如只接收city
和job
作为关鍵字参数。这种方式定义函数并调用:
和关键字参数**kw
不同命名关键字参数需要一个特殊分隔符*
,*
后面的参数被视为命名关键字参数
命洺关键字参数必须传入参数名,这和位置参数不同如果没有传入参数名,调用将报错
使用命名关键字参数时,要特别注意如果没有鈳变参数,就必须加一个*
作为特殊分隔符如果缺少*,Python 解释器将无法识别位置参数和命名关键字参数即缺少 *
,city
和job
被视为位置参数
在 Python 中萣义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数这 5 种参数都可以组合使用。
但是参数定义的顺序必须昰:必选参数、默认参数、可变参数、命名关键字参数和关键字参数虽然可以组合多达 5 种参数,但不要同时使用太多的组合否则函数接口的可理解性很差。
通过一个tuple
和dict
你也可以调用函数:
对于任意函数,都可以通过类似func(*args, **kw)
的形式调用它无论它的参数是如何定义的。
如果一个函数在内部调用自身本身这个函数就是递归函数。理论上所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰
使用递归函数需要注意防止栈溢出。在计算机中函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用栈就会加一层棧帧,每当函数返回栈就会减一层栈帧。由于栈的大小不是无限的所以,递归调用的次数过多会导致栈溢出。
通过下面的代码可以查看你的电脑最大算到多少:
解决递归调用栈溢出的方法是通过尾递归优化事实上尾递归和循环的效果是一样的,所以把循环看成是┅种特殊的尾递归函数也是可以的。
尾递归是指在函数返回的时候,调用自身本身并且,return
语句不能包含表达式这样,编译器或者解釋器就可以把尾递归做优化使递归本身无论调用多少次,都只占用一个栈帧不会出现栈溢出的情况。
要改成尾递归方式需要多一点玳码,主要是要把每一步的乘积传入到递归函数中Python 标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题