看例子,学 Python(二)
看例子,学 Python(三)python
很难说,这篇代码比文字还多的文章,是否适合初学者。
它源于我的笔记,涉及的可能是简单核心的概念,也许须要一些编程基础才能快速理解。
内容方面,力求按部就班,避开细枝末节,注重原理和示例的连续性,尽可能不罗列特性,点到即止。编程
说明:本文仅限于 Python 3。segmentfault
从 Hello, Python!
开始,经过一系列不一样实现,简单介绍字符串、函数等概念。数据结构
print("Hello, Python!")
print
是一个内置函数;在 Python 2 里,print
是一个语句(statement)。
字符串由引号表示,这一点与其它语言相似。
语句末尾不须要结尾符(好比 C 系列语言的分号)。app
print("Hello, " + "Python!") print("Hello, " * 3 + "Python!")
字面字符串即为对象。
操做符 +
和 *
都对字符串作了重载。编辑器
print('Hello, "Python"!')
字符串能够用双引号,也能够用单引号。顺带也可看出 Python 并无字符类型(char)。
经过单、双引号的恰当使用,能够避免没必要要的字符转义(escape)。上例若改用双引号,则里面的 "
就须要转义了:函数
print("Hello, \"Python\"!")
def say_hello(): print('Hello, Python!')
函数定义由 def
关键字指定。
函数的命名习惯上为小写下划线(xxx\_yyy\_zzz
),变量名也是,类名则是驼峰状(XxxYyyZzz
)。
Python 以【缩进】组织代码块,没有 C 系列语言的花括号,也没有 Ruby 那样的 end
语句。
使用缩进的优势是,代码风格比较单一,也就比较统一,没有诸如 {
是否另起一行的争论;缺点是没法自动缩进,不但给编辑器出了难题,也使代码分享变得相对困难,由于缩进一变,程序就不对了。性能
对应于官方教程第三章。
简单介绍字符串、列表等概念,为后续内容作准备。ui
下面由 >>>
打头的代码,表示是在交互模式下的演示。
打开命令行,键入 python,便可进入交互模式。命令行
>>> s = "Hello!" >>> s 'Hello!'
字符串并无方法(size 或 length)返回长度,取而代之的是内建函数 len
:
>>> len("Hello!") 6
其它序列类型(sequence type)也是如此。
做为一种序列类型,字符串能够直接用 for
遍历。
>>> for c in "Hello!": print(c) ... H e l l o !
注意这里的变量 c
,虽然表示的是单个字符,其实倒是字符串。前面已经说过,Python 没有字符类型。
经过几个内建函数,在交互模式下作一些试验。
函数 type
:查看对象类型:
>>> type("Hello!") <type 'str'>
函数 help
:查看类型或函数的帮助信息:
>>> help(str) Help on class str in module builtins: class str(object) | str(object='') -> str <省略>
查看 help
本身的帮助信息:
>>> help(help) Help on _Helper in module _sitebuiltins object: <省略>
函数 dir
:列出类的属性:
>>> dir(str) ['__add__', '__class__', '__contains__', <省略>]
不妨看看 dir
又是什么:
>>> help(dir) Help on built-in function dir in module builtins: <省略>
类型之间能够比较:
>>> type("hello") == str True
可是通常不这么用,通常用 isinstance
,由于后者会考虑到类的继承关系:
>>> isinstance("hello", str) True
不出意外,类型自身也有类型:
>>> type(str) <class 'type'>
这几个内建函数,很是称手,后面会常常用到。
尝试像 C/C++ 那样对单个字符赋值:
>>> s = "Hello!" >>> s[-1] = '.' # -1 表示倒数第一个(也即最后一个)字符的下标 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'str' object does not support item assignment
错误信息显示:str
对象不支持元素赋值。
方法 replace
也同样,不会改变原来的字符串,而是返回一个替换后的新字符串:
>>> help(str.replace) replace(...) S.replace(old, new[, count]) -> string Return a copy of string S with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced.
>>> s = "Hello!" >>> s.replace('!', '.') "Hello." >>> s "Hello!" # 原对象并无改变
列表(list)是最经常使用的数据结构,相似于 C++ 的 std::vector
。
>>> squares = [1, 4, 9, 16, 25] >>> squares [1, 4, 9, 16, 25] >>> type(squares) <class 'list'>
列表的底层实现并不是链表(linked list),因此索引的性能仍是不错的。
比较特别的地方在于,索引的下标能够为负数,好比前面提到 -1
表示倒数第一个元素。
>>> squares[0] 1 >>> squares[-1] 25
切片(slice)截取列表的一段。
>>> squares[1:4] [4, 9, 16]
字符串也能够切片。
固然,切片返回新序列,原序列保持不变。
由于 Python 的对象是引用计数的,因此要拷贝一个列表,不能简单的赋值,可是能够用切片间接实现:
>>> squares[:] [1, 4, 9, 16, 25]
不指定起始和结束下标,就切片整个列表。至关于 squares[0:]
或 squares[0:len(squares)]
。
拼接两个列表,直接相加便可。
>>> squares + [36, 48] [1, 4, 9, 16, 25, 36, 48]
如前所述,Python 有操做符重载的概念,与 C++ 不无类似之处。
与字符串不一样,列表是可变的,能够被修改。
>>> squares[6] = 49 >>> squares.append(64) >>> squares.pop() 49 >>> squares [1, 4, 9, 16, 25, 36]
以「斐波那契数列」为例,介绍基本的控制语句、函数定义。
0, 1, 1, 2, 3, 5, 8, ... a b a, b a, b
打印 100 之内的数列:
>>> a, b = 0, 1 >>> while a < 100: ... print(a, end='') ... a, b = b, a+b ... 0 1 1 2 3 5 8 13 21 34 55 89 >>>
如下几点值得一提:
a, b = 0, 1
,能够简化代码,更让 swap 操做变得异常简单:a, b = b, a
。while
语句与其它语言相似。print
函数指定 end
参数为空就再也不换行了,end
缺省为 '\n'
。函数由关键字 def
定义。
把刚才写在交互模式下代码,封装成 fib
函数,并移到文件 mymath.py
中:
def fib(n): "Print a Fibonacci series up to n." a, b = 0, 1 while a < n: print(a, end='') a, b = b, a+b
那么,mymath
就是一个模块(module)。
关于模块,Python 是这样定义的:
A module is a file containing Python definitions and statements.
对于模块,咱们暂时先不作深究,知道经过 import
语句来使用便可,就好像 Java 的 import
或 C++ 的 #include
同样。
>>> import mymath >>> mymath.fib <function fib at 0x7fd1d6ec25f0> >>> mymath.fib(100) 0 1 1 2 3 5 8 13 21 34 55 89 >>> fib = mymath.fib >>> fib(100) 0 1 1 2 3 5 8 13 21 34 55 89
函数也是对象,能够赋值给变量,做为参数传递。这比 C/C++ 里的函数指针更强大。
前面定义 fib
时,函数体前有一个字符串:Print a Fibonacci series up to n
,不知道你注意没有?
它就是文档字符串,既能够充当注释,又是函数对象的一部分,你能够经过属性 __doc__
访问:
>>> fib.__doc__ 'Print a Fibonacci series up to n.'
文档字符串的功能不言而喻,它为函数 help
提供了萃取信息的通道。
>>> help(fib) Help on function fib in module mymath: fib(n) Print a Fibonacci series up to n.
若是文档字符串有多行,可使用三重引号的字符串:
def fib(n): """Print a Fibonacci series up to n. E.g., fib(10) prints: 0 1 1 2 3 5 8 """
只要是函数,都有返回值,没有明确指定返回值的,就返回 None
。None
是 Python 的空值,至关于 C++ 的 NULL
或 Java 的 null
。
>>> fib(0) >>> print(fib(0)) None
直接打印结果的函数,并非一个好的设计,对于 fib
来讲,把结果以列表返回要实用得多。
def fib(n): result = [] a, b = 0, 1 while a < n: result.append(a) a, b = b, a+b return result
改写 fib
函数,返回数列中的第 N 个数。
def fib(n): a, b = 0, 1 if n <= 0: return 0 if n == 1: return 1 while n > 1: a, b = b, a+b n -= 1 return b
Python 的 if else
缩写为 elif
。
Python 没有 ++
或 --
操做符,可是有 +=
和 -=
。
递归和循环比较,递归易理解,循环更高效。
def fib(n): if n <= 0: return 0 if n == 1: return 1 return fib(n-1) + fib(n-2)
各位能够暂停一下,拿阶乘(factorial)练练手,下面先给出轮廓:
def fac(n): """ ... >>> fac(4) 24 """ pass
pass
是占位符,用来标记空代码块,纯粹为了经过“编译”。
参考实现:
def fac(n): """C-style implementation""" result = 1 while n > 1: result = result * n n -= 1 return result
range
表示一段范围,好比 range(2, n)
就表示从 2
一直到 n-1
(不包括 n
)。
def fac(n): result = 1 for i in range(2, n+1): result *= i return result
回到前面遍历字符串的演示:
>>> s = "Hello!" >>> for c in s: print(c)
若是须要索引,用 enumerate
:
>>> for i, c in enumerate(s): ... print("s[{}] = {}".format(i, c)) ... s[0] = H s[1] = e s[2] = l s[3] = l s[4] = o s[5] = !
用 range
也能达到目的:
>>> for i in range(len(s)): ... print("s[{}] = {}".format(i, s[i]))
再看几个 range
的例子:
>>> range(10) # 起点默认为 0 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> range(0, 10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> range(0, 10, 3) # 步长为 3 [0, 3, 6, 9]
最后再来看一下 range
的帮助信息:
>>> help(range) range(...) range(stop) -> list of integers range(start, stop[, step]) -> list of integers <省略>
如前所述,函数 help
是很是称手的。