Python基础入门

2014.02.22 | Comments

1. Python介绍

Python是一种解释性的面向对象的语言。Python使用C语言编写,不需要事先声明变量的类型(动态类型),但是一旦变量有了值,那么这个变脸是有一个类型的,不同类型的变量之间赋值需要类型转换(强类型)。

1.1 安装 Python

现在的操作系统都自带安装了 Python,要测试你是否安装了Python,你可以打开一个shell程序(就像konsole或gnome-terminal),然后输入如下所示的命令python -V

$ python -V
Python 2.7.4

如果你看见向上面所示的那样一些版本信息,那么你已经安装了Python了。

2. Python 基础

2.1 注释

无论是行注释还是段注释,均以 # 加一个空格来注释。

如果需要在代码中使用中文注释,必须在 python 文件的最前面加上如下注释说明:

# -* - coding: UTF-8 -* -

如下注释用于指定解释器:

#! /usr/bin/python

2.2 数据类型和变量

  • python的数字类型分为整型、长整型、浮点型、布尔型、复数类型、None类型。
  • python没有字符类型
  • python内部没有普通类型,任何类型都是对象。
  • 如果需要查看变量的类型,可以使用type类,该类可以返回变量的类型或创建一个新的类型。 python有3种表示字符串类型的方式,即单引号、双引号、三引号。单引号和双引号的作用是相同的。python程序员更喜欢用单引号,C/Java程序员则习惯使用双引号表示字符串。三引号中可以输入单引号、双引号或换行等字符。

变量命名规则:

  • 第一个字符必须是字母表中的字母(大写或小写)或者一个下划线(‘ _ ’)
  • 其他部分可以由字母(大写或小写)、下划线(‘ _ ’)或数字(0-9)组成
  • 对大小写敏感

python中的变量不需要声明,变量的赋值操作即使变量声明和定义的过程。

>>>a = 10

那么你的内存里就有了一个变量a, 它的值是10,它的类型是integer (整数)。 在此之前你不需要做什么特别的声明,而数据类型是Python自动决定的。

>>>print a
>>>print type(a)

那么会有如下输出:

10
<type 'int'>

这里,我们学到一个内置函数type(), 用以查询变量的类型。

如果你想让a存储不同的数据,你不需要删除原有变量就可以直接赋值。

>>>a = 1.3
>>>print a,type(a)

会有如下输出:

1.3 <type 'float'>

python 中一次新的赋值,将创建一个新的变量。即使变量的名称相同,变量的标识并不相同。用id()函数可以获取变量标识:

x = 1
print id(x)
x = 2
print id(x)

如果变量没有赋值,则python认为该变量不存在。

在函数之外定义的变量都可以称为全局变量。全局变量可以被文件内部的任何函数和外部文件访问。

全局变量建议在文件的开头定义,也可以把全局变量放到一个专门的文件中,然后通过import来引用

2.3 序列

sequence(序列)是一组有顺序的元素的集合。

  • 序列包括字符串、列表、元组。
  • 序列可以包含一个或多个元素,也可以没有任何元素。
  • 使用索引来访问序列,索引从0开始。
  • 可以使用分片操作来访问一定范围内的元素。

序列有两种:tuple(定值表; 也有翻译为元组) 和 list (表)。tuple 和 list 的主要区别在于,一旦建立,tuple 的各个元素不可再变更,而 list 的各个元素可以再变更。

>>>s1 = (2, 1.3, 'love', 5.6, 9, 12, False)         # s1是一个tuple
>>>s2 = [True, 5, 'smile']                          # s2是一个list
>>>print s1,type(s1)
>>>print s2,type(s2)

序列可以进行相加和乘法等操作:

>>> [1,2]+[3,4]
  [1,2,3,4]

#列表和字符串是无法连接在一起的
>>> "hello,"+"world!"
  "hello,world!"

>>> "a" * 5
  "aaaaa"
>>> [2] * 5
  [2,2,2,2,2]

#初始化一个长度为3的空序列
>>> seq=[None] * 3
  [None,None,Noe]

#判断一个元素是否存在于序列中
>>> permissions='rw'
>>> 'w' in permissions
  True

>>> users=['a','b','c']
>>> 'a' in users
  True

>>> database=[
  ['a','1234'],
  ['b','2344']
]
>>> ['c','1234'] in database
  False

2.4. 列表

列表类似于c语言中的数组,用于存储顺序结构。例如:[1,2,3,4,5]。列表中的各个元素可以是任意类型,元素之间用逗号分隔。列表的下标从0开始,和c语言类似,但是增加了负下标的使用。

对列表的操作:

>>> names=['zhangsan','lisi','lili','wangwu']

#删除
>>> del names[0]

#分片赋值
>>> names[1:]=list('ab') #list函数用于将字符串转换为列表
>>> names
  ['lisi','a','b']

#在不需要替换任何原有元素的情况下插入新元素
>>> names[1:1]=['c','d']
>>> names
  ['lisi','c','d','a','b']
>>> names[1:4]=[]
>>> names
  ['lisi','b']

#添加
>>> names.append('bb')
>>> names.count('b')

#extend效率高于连接操作
>>> names.extend(['c','e','d'])
>>> names
  ['lisi','b','bb','c','e','d']

>>> names.index('lisi')
>>> names.insert(1,'a')
>>> names.pop()
  'e'
>>> names.remove('lisi')
>>> names
  ['a','b','bb','c','e','d']
>>> names.reverse()
  ['d','e','c','bb','b','a']

#排序
>>> names.sort()
  ['a','b','bb','c','d','e']
>>> sorted(names)
  ['a','b','bb','c','d','e']

#高级排序
>>> names.sort(cmp)
>>> names.sort(key=len)
>>> names.sort(reverse=True)

2.5 元组

元组 tuple 是常量 list。tuple 不能 pop,remove,insert 等方法。 - tuple 用 () 表示,如 a=(1,2,3,4),括号可以省略。 - tuple 可以用下标返回元素或者子 tuple - tuple 可以用于多个变量的赋值。例如:a,b=(1,2) - 表示只含有一个元素的 tuple 的方法是:(1,),后面有个逗号,用来和单独的变量相区分。 - 字符串是一种特殊的元素,因此可以执行元组的相关操作。

tuple 比 list 性能好,也就是不用提供动态内存管理的功能。

#定义一个元组
>>> 1,2,3
  (1,2,3)

#空的元组
>>> ()

>>> 42
  42
>>> 42,
  (42,)
>>> (42,)
  (42,)

#tuple函数
>>> tuple([1,2,3])
  (1,2,3)
>>> tuple('abc')
  ('a','b','c')
>>> tuple((1,2,3))
  (1,2,3)

>>> x=1,2,3
>>> x[1]
  2
>>> x[0:2]
  (1,2)

2.6 字典

字典是一个无序存储结构。每一个元素是一个 pair,包括 key 和 value 两个不服。key 的类型是 integer 或者 string 或者任何同时含有 __hash____cmp__ 的对象。字典中没有重复的 key,其每一个元素是一个元组。

创建和使用字典:

phonebook = {'zhangsan':'1234',"lisi":'1231'}

dict函数:

>>> items = [('name','aa'),('age',18)]
>>> d = dict(items)
>>> d
  {'age':18,'name':'aa'}

>>> d = dict(name='aa',age=18)
>>> d
  {'age':18,'name':'aa'}

字典的基本操作:

2.7 set

set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。

要创建一个set,需要提供一个list作为输入集合:

>>> s = set([1, 2, 3])
>>> s
set([1, 2, 3])

注意,传入的参数[1, 2, 3]是一个list,而显示的set([1, 2, 3])只是告诉你这个set内部有1,2,3这3个元素,显示的[]不表示这是一个list。

重复元素在set中自动被过滤:

>>> s = set([1, 1, 2, 2, 3, 3])
>>> s
set([1, 2, 3])

通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果:

~~~python
>>> s.add(4)
>>> s
set([1, 2, 3, 4])
>>> s.add(4)
>>> s
set([1, 2, 3, 4])

通过remove(key)方法可以删除元素:

>>> s.remove(4)
>>> s
set([1, 2, 3])

set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:

>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s1 & s2
set([2, 3])
>>> s1 | s2
set([1, 2, 3, 4])

set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”。试试把list放入set,看看是否会报错。

2.8 字符串

字符串

普通字符串使用双引号或者单引号或者 """ 来表示。例如:

print "hello,world !"

print "hello,\
world !"

print '''
    hello,world!
'''

print """
    hello,world!
"""

自然字符串

如果你想要指示某些不需要如转义符那样的特别处理的字符串,那么你需要指定一个自然字符串。自然字符串通过给字符串加上前缀 rR 来指定。例如

r"Newlines are indicated by \n".

注意:自然字符串结尾不能输入反斜线

Unicode字符串

Unicode 是书写国际文本的标准方法。如果你想要用你的母语如北印度语或阿拉伯语写文本,那么你需要有一个支持 Unicode 的编辑器。类似地,Python 允许你处理 Unicode 文本——你只需要在字符串前加上前缀 uU。例如:

u"This is a Unicode string.".

Python 中的普通字符串在内部是以8位的 ascii 码形式存储的,而 Unicode 字符串则存储为16位 Unicode 字符。

记住,在你处理文本文件的时候使用 Unicode 字符串,特别是当你知道这个文件含有用非英语的语言写的文本。

3. 函数

  • python程序由包(package)、模块(module)和函数组成。包是由一系列模块组成的集合。模块是处理某一类问题的函数和类的集合。
  • 包就是一个完成特定任务的工具箱。
  • 包必须含有一个__init__.py文件,它用于标识当前文件夹是一个包。
  • python的程序是由一个个模块组成的。模块把一组相关的函数或代码组织到一个文件中,一个文件即是一个模块。模块由代码、函数和类组成。导入模块使用import语句。
  • 包的作用是实现程序的重用。
  • 函数是一段可以重复多次调用的代码。
  • 函数返回值可以用return来控制。

3.1 定义函数

函数定义示例如下:

def function_arithmetic(x,y,operator):
    '''
    usage: function for arithmetic
    '''
    result = {
      "+":x+y,
      "-":x-y,
      "*":x*y,
      "/":x/y
    }
    return result

# 函数名称
func_name = function_arithmetic.__name__
name = '%s' % func_name.replace('_', '-').strip('-')
# 函数doc 文档
help_ = function_arithmetic.__doc__.strip()

print func_name
print name
print help_

3.2 函数的参数

默认参数

最有用的形式是为一个或更多参数指定默认值。这样创建的函式调用时可以不用给足参数.。例如:

def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
    pass

关键字参数

函式也可以通过 keyword = value 形式的关键字参数来调用。例如:

ask_ok('ok?',complaint='Yes or no, please!')

可变参数

在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

>>> calc(1, 2)
5
>>> calc()
0

>>> nums = [1, 2, 3]
>>> calc(*nums)
14

关键字参数

可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。请看示例:

def person(name, age, **kw):
    print 'name:', name, 'age:', age, 'other:', kw

函数person除了必选参数name和age外,还接受关键字参数kw。在调用该函数时,可以只传入必选参数:

>>> person('Michael', 30)
name: Michael age: 30 other: {}

也可以传入任意个数的关键字参数:

>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

参数组合

在Python中定义函数,可以用必选参数、默认参数、可变参数和关键字参数,这4种参数都可以一起使用,或者只用其中某些,但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数和关键字参数。

比如定义一个函数,包含上述4种参数:

def func(a, b, c=0, *args, **kw):
    print 'a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw

在函数调用的时候,Python解释器自动按照参数位置和参数名把对应的参数传进去。

>>> func(1, 2)
a = 1 b = 2 c = 0 args = () kw = {}
>>> func(1, 2, c=3)
a = 1 b = 2 c = 3 args = () kw = {}
>>> func(1, 2, 3, 'a', 'b')
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
>>> func(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}

最神奇的是通过一个tuple和dict,你也可以调用该函数:

>>> args = (1, 2, 3, 4)
>>> kw = {'x': 99}
>>> func(*args, **kw)
a = 1 b = 2 c = 3 args = (4,) kw = {'x': 99}

所以,对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的。

参数列表解包

也存在相反的情形: 当参数存在于一个既存的列表或者元组之中, 但却需要解包以若干位置参数的形式被函数调用. 例如, 内建的 range() 函数期望接收分别的开始和结束的位置参数. 如果它们不是分别可用 (而是同时存在于一个列表或者元组中), 下面是一个利用 * 操作符解从列表或者元组中解包参数以供函数调用的例子:

>>> x,y,z=1,2,3
>>> print x,y,z
  1 2 3

#交换值
>>> x,y=y,x

>>> phonebook = {'zhangsan':'1234',"lisi":'1231'}
>>> key,value=phonebook.popitem()

>>> list(range(3, 6))            # 使用分离的参数正常调用
[3, 4, 5]
>>> args = [3, 6]
>>> list(range(*args))           # 通过解包列表参数调用
[3, 4, 5]

同样的, 字典可以通过 ** 操作符来解包参数:

>>> def parrot(voltage, state='a stiff', action='voom'):
     print("-- This parrot wouldn't", action, end=' ')
     print("if you put", voltage, "volts through it.", end=' ')
     print("E's", state, "!")

>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
 This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised

4. 流程控制

4.1 if 语句

>>> x = int(input("Please enter an integer: "))
Please enter an integer: 42
>>> if x < 0:
      x = 0
      print('Negative changed to zero')
 elif x == 0:
      print('Zero')
 elif x == 1:
      print('Single')
 else:
      print('More')

4.2 for 语句

Python中的 for 语句与你在 C 或是 Pascal 中使用的略有不同. 不同于在 Pascal 中总是依据一个等差的数值序列迭代, 也不同于在 C 中允许用户同时定义迭代步骤和终止条件, Python中的 for 语句在任意序列 (列表或者字符串) 中迭代时, 总是按照元素在序列中的出现顺序依次迭代.

 a = ['cat', 'window', 'defenestrate']
>>> for x in a:
     print(x, len(x))

在循环过程中修改被迭代的对象是不安全的 (这只可能发生在可变序列类型上,如列表)。

若想在循环体内修改你正迭代的序列 (例如复制序列中选定的项), 最好是先制作一个副本。

而切片则让这种操作十分方便:

>>> for x in a[:]: # 制造整个列表的切片复本
    if len(x) > 6: a.insert(0, x)

4.4 pass 语句

pass 语句什么都不做. 当语法上需要一个语句, 但程序不要动作时, 就可以使用它. 例如:

>>> while True:
     pass  # 忙等待键盘中断 (Ctrl+C)

一般也可以用于创建最小类:

>>> class MyEmptyClass:
     pass

另一个使用 pass 的地方是,作为函式或条件体的占位符,当你在新代码工作时,它让你能保持在更抽象的级别思考。 pass 会被默默地被忽略:

>>> def initlog(*args):
     pass   # 记得实现这里!

5. 高级特性

5.1 切片

下面这部分内容来自 廖雪峰的Python教程-切片

取一个list或tuple的部分元素是非常常见的操作。比如,一个list如下:

>>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']

取前3个元素,用一行代码就可以完成切片:

>>> L[0:3]
['Michael', 'Sarah', 'Tracy']

L[0:3] 表示,从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2,正好是3个元素。

如果第一个索引是0,还可以省略:

>>> L[:3]
['Michael', 'Sarah', 'Tracy']

也可以从索引1开始,取出2个元素出来:

>>> L[1:3]
['Sarah', 'Tracy']

类似的,既然Python支持 L[-1] 取倒数第一个元素,那么它同样支持倒数切片,试试:

>>> L[-2:]
['Bob', 'Jack']
>>> L[-2:-1]
['Bob']

记住倒数第一个元素的索引是 -1

切片操作十分有用。我们先创建一个0-99的数列:

>>> L = range(100)
>>> L
[0, 1, 2, 3, ..., 99]

可以通过切片轻松取出某一段数列。比如前10个数:

>>> L[:10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

后10个数:

>>> L[-10:]
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]

前11-20个数:

>>> L[10:20]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

前10个数,每两个取一个:

>>> L[:10:2]
[0, 2, 4, 6, 8]

所有数,每5个取一个:

>>> L[::5]
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]

甚至什么都不写,只写 [:] 就可以原样复制一个list:

>>> L[:]
[0, 1, 2, 3, ..., 99]

tuple 也是一种 list,唯一区别是 tuple 不可变。因此,tuple 也可以用切片操作,只是操作的结果仍是 tuple:

>>> (0, 1, 2, 3, 4, 5)[:3]
(0, 1, 2)

字符串 ‘xxx’ 或 Unicode 字符串 u’xxx’ 也可以看成是一种 list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串:

>>> 'ABCDEFG'[:3]
'ABC'
>>> 'ABCDEFG'[::2]
'ACEG'
Try

5.2 迭代

使用 for 关键字来迭代序列、字段或者可迭代的对象。

d = {'a': 1, 'b': 2, 'c': 3}

# 迭代字段的 key
for key in d:
  print key

# 迭代字段的 value
for value in d.itervalues():
  print print

# 迭代字符串
for ch in 'ABC':
  print ch

# Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身
for i, value in enumerate(['A', 'B', 'C']):
  print i, value

判断一个对象是否支持迭代:

>>> from collections import Iterable
>>> isinstance('abc', Iterable) # str是否可迭代
True
>>> isinstance([1,2,3], Iterable) # list是否可迭代
True
>>> isinstance(123, Iterable) # 整数是否可迭代
False

5.3 列表推导式

>>> [x*x for x in range(7)]
 [0,1,4,9,16,25,36]

>>> [x*x for x in range(7) if x%3 ==0 ]
 [0,9,36]

>>> [(x,y) for x in range(3) for y in range(2)]
  [(0,0),(0,1),(1,0),(1,1),(2,0),(2,1)]

另一个使用列表推导式的代码示例:

num = [1, 4, -5, 10, -7, 2, 3, -1]

def square_generator(optional_parameter):
    return (x ** 2 for x in num if x > optional_parameter)

print square_generator(0)
# <generator object <genexpr> at 0x004E6418>

# Option I
for k in square_generator(0):
    print k
# 1, 16, 100, 4, 9

# Option II
g = list(square_generator(0))
print g
# [1, 16, 100, 4, 9]

5.4 生成器

除非特殊的原因,应该经常在代码中使用生成器表达式。但除非是面对非常大的列表,否则是不会看出明显区别的。

使用生成器得到当前目录及其子目录中的所有文件的代码,下面代码来自 伯乐在线-python高级编程技巧

import os
def tree(top):
    #path,folder list,file list
    for path, names, fnames in os.walk(top):
        for fname in fnames:
            yield os.path.join(path, fname)

for name in tree(os.getcwd()):
    print name

参考文章


原创文章,转载请注明: 转载自JavaChen Blog,作者:JavaChen
本文链接地址:http://blog.javachen.com/2014/02/22/python-introduction-of-basics.html
本文基于署名2.5中国大陆许可协议发布,欢迎转载、演绎或用于商业目的,但是必须保留本文署名和文章链接。 如您有任何疑问或者授权方面的协商,请邮件联系我。