continue 语句
continue 语句被用来告诉Python跳过当前循环块中的剩余语句,然后 继续 进行下一轮循环。
break 语句 和 continue 语句 对于 while 循环 和 for 循环 都有效。
例(2.x写法):
while True:
s = raw_input('Enter something : ')
if s == 'quit':
break
if len(s) < 3:
print 'Input is not of sufficient length'
continue
# Do other kinds of processing here...
print 'Length of the string is', len(s)
例(3.x写法):
while True:
s = input('Enter something : ') # 3.x用input()代替raw_input(),且会获取结尾输入的换行符
s = s[:-1] # 去掉结尾的换行符
if s == 'quit':
break
if len(s) < 3:
print('Input is not of sufficient length')
continue
# Do other kinds of processing here...
print('Length of the string is', len(s))
函数:
定义函数
函数通过def关键字定义。
def关键字后跟一个函数的 标识符 名称,然后跟一对圆括号。圆括号之中可以包括一些变量名,该行以冒号结尾。
接下来是一块语句,它们是函数体。
例:
def sayHello():
print('Hello World!') # block belonging to the function
sayHello() # call the function
函数形参
函数中的参数名称为 形参 而你提供给函数调用的值称为 实参 。
局部变量
当你在函数定义内声明变量的时候,它们与函数外具有相同名称的其他变量没有任何关系,即变量名称对于函数来说是 局部 的。
这称为变量的 作用域 。所有变量的作用域是它们被定义的块,从它们的名称被定义的那点开始。
例:
x = 50
def func(x):
print('x is', x)
x = 2
print('Changed local x to', x) # 打印: 2
func(x)
print('x is still', x) # 打印: 50, 值没有变
global 语句
如果要为一个定义在函数外的变量赋值,那么你就得告诉Python这个变量名不是局部的,而是 全局 的。使用global语句完成这一功能。
没有global语句,是不可能为定义在函数外的变量赋值的。
你可以使用定义在函数外的变量的值(假设在函数内没有同名的变量)。然而,应避免这样做,因为这降低程序的可读性,不清楚变量在哪里定义的。
使用global语句可以清楚地表明变量是在外面的块定义的。
注:可以使用同一个global语句指定多个全局变量。例如 global x, y, z。
例:
def func():
global x
print('x is', x)
x = 2
print('Changed local x to', x) # 打印: 2
x = 50
func()
print('Value of x is', x) # 打印: 2, 值被改变了
默认参数值
如果希望一些参数是 可选 的,这些参数可使用默认值。
可以在函数定义的形参名后加上赋值运算符(=)和默认值,从而给形参指定默认参数值。
注意,默认参数值应该是一个参数。
例:
def say(message, times = 2):
print(message * times)
say('Hello ') # 打印:Hello Hello
say('World ', 5) # 打印:World World World World World
重要:
只有在形参表末尾的那些参数可以有默认参数值,即不能在声明函数形参的时候,先声明有默认值的形参而后声明没有默认值的形参。
这是因为赋给形参的值是根据位置而赋值的。例如,def func(a, b=5)是有效的,但是def func(a=5, b)是 无效 的。
关键参数
如果某个函数有许多参数,而你只想指定其中的一部分,那么可以通过命名来为这些参数赋值
——这被称作 关键参数 ——使用名字(关键字)而不是位置来给函数指定实参。
这样做有两个优势:
一、由于我们不必担心参数的顺序,使用函数变得更加简单了。
二、假设其他参数都有默认值,我们可以只给我们想要的那些参数赋值。
例:
def func(a, b=5, c=10):
print('a is', a, 'and b is', b, 'and c is', c)
func(3, 7) # 参数a得到值3,参数b得到值7,而参数c使用默认值10。
func(25, c=24) # 根据实参的位置,变量a得到值25。根据命名,即关键参数,参数c得到值24。变量b根据默认值,为5。
func(c=50, a=100) # 使用关键参数来完全指定参数值。a得到值100,c得到值50。变量b根据默认值,为5。
return 语句
return语句用来从一个函数 返回 即跳出函数。我们也可选从函数 返回一个值 。
例:
def maximum(x, y):
if x > y:
return x
else:
return y
print(maximum(2, 3)) # 打印 3
None
None 是Python中表示没有任何东西的特殊类型(相当于java的 null)。例如,如果一个变量的值为None,可以表示它没有值。
注意:函数没有返回值的,等价于最后返回return None。通过运行print someFunction(),你可以明白这一点。
例:
def someFunction():
# pass语句在Python中表示一个空的语句块。它后面的代码会照常运行。
pass
print(someFunction())
DocStrings
DocStrings:文档字符串。它是一个重要的工具,帮助你的程序文档更加简单易懂,应该尽量使用它。甚至可以在程序运行的时候,从函数恢复文档字符串!
在函数的第一个逻辑行的字符串是这个函数的 文档字符串 。注意,DocStrings也适用于模块和类。
文档字符串的惯例是一个多行字符串,它的首行以大写字母开始,句号结尾。第二行是空行,从第三行开始是详细的描述。 强烈建议遵循这个惯例。
例:
def printMax(x, y):
'''Prints the maximum of two numbers.
The two values must be integers.'''
x = int(x) # convert to integers, if possible
y = int(y)
if x > y:
print(x, 'is maximum')
else:
print(y, 'is maximum')
printMax(3, 5) # 打印: 5 is maximum
print(printMax.__doc__) # 打印: Prints the maximum ... must be integers.
注:
使用__doc__(注意是两个下划线)调用printMax函数的文档字符串属性。请记住Python把 每一样东西 都作为对象,包括这个函数。
Python中help()函数即是使用DocStings的了,它只是抓取函数的__doc__属性,然后整洁地展示给你。可以对上面的函数尝试一下: help(printMax)。记住按q退出help。
自动化工具也可以以同样的方式从你的程序中提取文档。因此强烈建议你对你所写的任何正式函数编写文档字符串。
函数属性 func_*
在Python 2里,函数的里的代码可以访问到函数本身的特殊属性。在Python 3里,为了一致性,这些特殊属性被重新命名了。
Python 2 与 Python 3 的比较
Python 2 Python 3 说明
① a_function.func_name a_function.__name__ # 包含了函数的名字。
② a_function.func_doc a_function.__doc__ # 包含了在函数源代码里定义的文档字符串(docstring)。
③ a_function.func_defaults a_function.__defaults__ # 是一个保存参数默认值的元组。
④ a_function.func_dict a_function.__dict__ # 一个支持任意函数属性的名字空间。
⑤ a_function.func_closure a_function.__closure__ # 一个由cell对象组成的元组,包含了函数对自由变量(free variable)的绑定。
⑥ a_function.func_globals a_function.__globals__ # 一个对模块全局名字空间的引用,函数本身在这个名字空间里被定义。
⑦ a_function.func_code a_function.__code__ # 一个代码对象,表示编译后的函数体。
模块:
如果要在其他程序中重用很多函数,那么你该使用模块。
模块基本上就是一个包含了所有你定义的函数和变量的文件。
为了在其他程序中重用模块,模块的文件名必须以.py为扩展名。
sys模块(标准库模块)
sys模块包含了与Python解释器和它的环境有关的函数。
例:
import sys # 输入 sys模块。基本上,这句语句告诉Python,我们想要使用这个模块。
print('The command line arguments are:')
# 打印调用文件的命令行参数
for i in sys.argv:
print(i)
print('\nThe PYTHONPATH is', sys.path)
输出:
$ python using_sys.py we are arguments
The command line arguments are:
using_sys.py
we
are
arguments
The PYTHONPATH is ['/home/swaroop/byte/code', '/usr/lib/python23.zip',
'/usr/lib/python2.3', '/usr/lib/python2.3/plat-linux2',
'/usr/lib/python2.3/lib-tk', '/usr/lib/python2.3/lib-dynload',
'/usr/lib/python2.3/site-packages', '/usr/lib/python2.3/site-packages/gtk-2.0']
注:
执行 import sys 语句的时候,它在 sys.path 变量中所列目录中寻找 sys.py 模块。
如果找到了这个文件,这个模块的主块中的语句将被运行,然后这个模块将能够被你使用。
注意,初始化过程仅在我们 第一次 输入模块的时候进行。另外,“sys”是“system”的缩写。
脚本的名称总是sys.argv列表的第一个参数。所以,在这里,'using_sys.py'是sys.argv[0]、'we'是sys.argv[1]。
sys.path包含输入模块的目录名列表。
可以观察到sys.path的第一个字符串是空的——这个空的字符串表示当前目录也是sys.path的一部分,这与PYTHONPATH环境变量是相同的。
这意味着你可以直接输入位于当前目录的模块。否则,你得把你的模块放在sys.path所列的目录之一。
另外:
sys.exit() # 程序结束
sys.stdin、 sys.stdout 和 sys.stderr 分别对应你的程序的标准输入、标准输出和标准错误流。
字节编译的.pyc文件
输入一个模块相对来说是一个比较费时的事情,所以Python做了一些技巧,以便使输入模块更加快一些。
一种方法是创建 字节编译的文件,这些文件以.pyc作为扩展名。另外,这些字节编译的文件也是与平台无关的。
当你在下次从别的程序输入这个模块的时候,.pyc文件是十分有用的——它会快得多,因为一部分输入模块所需的处理已经完成了。
from ... import 语句
如果你想要直接输入 argv 变量到你的程序中(避免在每次使用它时打sys.),那么你可以使用 from sys import argv 语句。
如果你想要输入所有 sys 模块使用的名字,那么你可以使用 from sys import *语句。
这对于所有模块都适用。
注意:
1.使用 from package import item 方式导入包时,这个子项(item)既可以是包中的一个子模块(或一个子包),也可以是包中定义的其它命名,像函数、类或变量。
import 语句首先核对是否包中有这个子项,如果没有,它假定这是一个模块,并尝试加载它。如果没有找到它,会引发一个 ImportError 异常。
2.使用像 import item.subitem.subsubitem 这样的语句时,这些子项必须是包,最后的子项可以是包或模块,但不能是前面子项中定义的类、函数或变量。
3.应该避免使用 from...import 而使用 import 语句,因为这样可以使你的程序更加易读,也可以避免名称的冲突。
import ... as
为 import 的模块起一个简称。如: import cPickle as p
起简称后,下面的语句即可使用简称,如原本的 cPickle.dump() 可写成 p.dump()
模块的 __name__
每个模块都有一个名称,在模块中可以通过语句来找出模块的名称。
这在一个场合特别有用——就如前面所提到的,当一个模块被第一次输入的时候,这个模块的主块将被运行。
假如我们只想在程序本身被使用的时候运行主块,而在它被别的模块输入的时候不运行主块,我们该怎么做呢?这可以通过模块的__name__属性完成。
每个Python模块都有它的__name__,如果它是'__main__',这说明这个模块被用户单独运行,我们可以进行相应的恰当操作。
例:
# Filename: using_name.py
if __name__ == '__main__':
print('This program is being run by itself')
else:
print('I am being imported from another module')
输出:
$ python using_name.py
This program is being run by itself
$ python
>>> import using_name
I am being imported from another module
自定义模块
每个Python程序也是一个模块。
模块,例:
# Filename: mymodule.py
def sayhi():
print('Hi, this is mymodule speaking.')
version = '0.1'
# End of mymodule.py
上面是一个 模块 的例子。你已经看到,它与我们普通的Python程序相比并没有什么特别之处。
记住这个模块应该被放置在我们输入它的程序的同一个目录中,或者在 sys.path 所列目录之一。
用例1:
import mymodule
mymodule.sayhi()
print('Version', mymodule.version)
注:函数和成员都以点号来使用。
用例2: 使用from..import语法的版本。
from mymodule import sayhi, version # 或者写: from mymodule import *
sayhi()
print('Version', version)
包(Packages)
包通常是使用用“圆点模块名”的结构化模块命名空间。例如, A.B 表示名为"A" 的包中含有名为"B"的子模块。
使用圆点模块名保存不同类库的包可以避免模块之间的命名冲突。(如同用模块来保存不同的模块架构可以避免变量之间的命名冲突)
包目录必须要有一个 __init__.py 文件的存在;这是为了防止命名冲突而无意中在随后的模块搜索路径中覆盖了正确的模块。
最简单的情况下, __init__.py 可以只是一个空文件,不过它也可能包含了包的初始化代码,或者设置了 __all__ 变量。
dir()函数
使用内建的dir函数来列出模块定义的标识符。标识符有函数、类和变量。
当你为 dir()提供一个模块名的时候,它返回模块定义的名称列表。如果不提供参数,它返回当前模块中定义的名称列表。
$ python
>>> import sys
>>> dir(sys) # get list of attributes for sys module
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__',
'__stdin__', '__stdout__', '_getframe', 'api_version', 'argv',
'builtin_module_names', 'byteorder', 'call_tracing', 'callstats',
'copyright', 'displayhook', 'exc_clear', 'exc_info', 'exc_type',
'excepthook', 'exec_prefix', 'executable', 'exit', 'getcheckinterval',
'getdefaultencoding', 'getdlopenflags', 'getfilesystemencoding',
'getrecursionlimit', 'getrefcount', 'hexversion', 'maxint', 'maxunicode',
'meta_path','modules', 'path', 'path_hooks', 'path_importer_cache',
'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags',
'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout',
'version', 'version_info', 'warnoptions']
>>> dir() # get list of attributes for current module
['__builtins__', '__doc__', '__name__', 'sys']
>>>
>>> a = 5 # create a new variable 'a'
>>> dir()
['__builtins__', '__doc__', '__name__', 'a', 'sys']
>>>
>>> del a # delete/remove a name; 这个得留意
>>>
>>> dir()
['__builtins__', '__doc__', '__name__', 'sys']
>>>
数据结构
可以处理一些 数据 的 结构 。或者说,它们是用来存储一组相关数据的。
在Python中有三种内建的数据结构——列表、元组和字典。
列表(list, 有的语言称为:数组)
是处理一组有序项目的数据结构,即你可以在一个列表中存储一个 序列 的项目。
列表中的项目应该包括在方括号中,每个项目之间用逗号分割。
可以添加、删除或是搜索列表中的项目。列表是 可变的 数据类型。
列表对象定义的所有方法可以通过 help(list) 获得完整的知识。我比较习惯称它为“数组”。
例:
shoplist = ['apple', 'mango', 'carrot', 'banana']
#查看长度
print('I have', len(shoplist),'items to purchase.')
#遍历
print('These items are:', end=' ') # 注意这行的结尾,打印时可以不换行,python 2.x应该用逗号结尾
for item in shoplist:
print(item, end=' ') # python 2.x 此行应该写:“print item,”
#添加
print('\nI also have to buy rice.')
shoplist.append('rice')
print('My shopping list is now:', shoplist)
#排序
print('I will sort my list now')
shoplist.sort()
print('Sorted shopping list is:', shoplist)
#删除,以及使用下标
print('The first item I will buy is:', shoplist[0])
olditem = shoplist[0]
del shoplist[0]
print('I bought the', olditem)
print('My shopping list is now:', shoplist)
#多维列表时,保存的对象只是引用
newlist = ['waa','dd']
shoplist.append(newlist)
print('My shopping list is now:', shoplist)
del newlist[0]
print('My shopping list is now', shoplist)
# 删除重复, 用 set (对元组也可以这样写)
L = [1,1,1,2,2]
print(list(set(L))) # 打印:[1, 2]
l = [(1, 2), (1, 2), 3, 5, 4, 3, 4, (1, 2), 0, 5]
l = list(set(l))
print(l) # 打印: [(1, 2), 0, 3, 4, 5]
# 复制列表(浅拷贝)
c = shoplist[:]
# 复制(深拷贝)
import copy
c = copy.deepcopy(shoplist)
元组(tuple)
元组和列表十分类似,只不过元组和字符串一样是 不可变的 即你不能修改元组。
元组通过圆括号中用逗号分割的项目定义。
元组通常用在使语句或用户定义的函数能够安全地采用一组值的时候,即被使用的元组的值不会改变。
如果你想要知道元组对象定义的所有方法,可以通过 help(tuple) 获得完整的知识。
例:
#一维元组
zoo = ('wolf', 'elephant', 'penguin')
print('Number of animals in the zoo is %s' % len(zoo)) # 打印: 3
newlist = ['waa','dd']
#多维元组
new_zoo = ('monkey', 'dolphin', zoo, newlist)
print('Number of animals in the new zoo is %s' % len(new_zoo)) # 打印: 3
print('All animals in new zoo are %s' % str(new_zoo)) # 打印: ('monkey','dolphin',('wolf','elephant','penguin'),['waa','dd'])
print('Animals brought from old zoo are %s' % str(new_zoo[2])) # 打印: ('wolf', 'elephant', 'penguin')
print('Last animal brought from old zoo is %s' % new_zoo[2][2]) # 打印: penguin
#多维元组时,保存的对象只是引用
del newlist[0]
print('new_zoo is now:' + str(new_zoo) ) # 打印: ('monkey','dolphin',('wolf','elephant','penguin'),['dd'])
注意:含有0个或1个项目的元组
一个空的元组(含有0个项目)由一对空的圆括号组成,如myempty = ()。
含有单个元素的元组必须在第一个(唯一一个)项目后跟一个逗号。如: singleton = (2 , )。
如果小括号里面只有唯一一个项目,而这个项目后面又没有跟一个逗号的话,Python会认为它是一个表达式。
字典(dict, 有的语言称为:json)
字典把键(名字)和值(详细情况)联系在一起。
注意,键必须是唯一的,且只能使用不可变的对象(比如字符串)来作为字典的键,但字典的值没有此限制。应该说只能使用简单的对象作为键。
键值对在字典中以这样的方式标记:d = {key1 : value1, key2 : value2 }。
键值对用冒号分割,而各个对用逗号分割,所有这些都包括在花括号中。
记住字典中的键/值对是没有顺序的。如果要一个特定的顺序,那么应该在使用前自己对它们排序。
字典是dict类的实例/对象,可以用 help(dict) 来查看其属性和函数。
例:
ab = { 'Swaroop': 'swar',
'Larry' : 'larry',
'Spammer': 'spammer'
}
print(ab) # 打印: {'Swaroop':'swar', 'Larry':'larry', 'Spammer':'spammer'}
print("Swaroop's address is %s" % ab['Swaroop']) # 打印: swar
# 添加值,或者设值
ab['Guido'] = 'guido'
# 删除值
del ab['Spammer']
# ab.pop('Spammer') # 也可以用 pop 来删除,但建议后面的这种写法,避免没有这个键时会报错: ab.pop('Spammer', None)
print('\nThere are %d contacts in the address-book\n' % len(ab)) # 打印: 3
# 遍历(这写法得留意)
for name, address in ab.items():
print('Contact %s at %s' % (name, address))
# 包含key
if 'Guido' in ab: # 或者写: if ab.has_key('Guido'):
print("\nGuido's address is %s" % ab['Guido'])
# 原字典上创建新字典
print(ab) # 打印: {'Swaroop':'swar', 'Larry':'larry', 'Guido':'guido'}
dd = dict(ab, slug_field='slug', test=5) # 创建新字典,字典作为参数的只能放第一个,其余不能再是字典;字典参数可省略
print(dd) # 打印: {'Swaroop':'swar', 'test':5, 'slug_field':'slug', 'Larry':'larry', 'Guido':'guido'}
# 建议的取值方法
print( ab['test'] ) # 这样取值,当字典里面没有对应的key时会报错:“KeyError”
print( ab.get('test', 'default_value') ) # get取值,当字典里面没有对应的key时可取后面的预设值,预设值是可选的(默认是 None)
# 所有的键和值
print(ab.keys()) # 所有的键
print(ab.values()) # 所有的值
# 复制(浅拷贝)
print(ab.copy())
# 复制(深拷贝)
import copy
c = copy.deepcopy(ab)
序列
列表、元组和字符串都是序列,序列的两个主要特点是“索引”操作符和“切片”操作符。
索引操作符让我们可以从序列中抓取一个特定项目。(即使用下标)
切片操作符让我们能够获取序列的一个切片,即一部分序列。(即在下标的中括号里面使用冒号)
例:
shoplist = ['apple', 'mango', 'carrot', 'banana']
# Indexing or 'Subscription' operation
print('Item 0 is %s' % shoplist[0])
print('Item 3 is %s' % shoplist[3])
print('Item -1 is %s' % shoplist[-1]) # 打印:banana 即倒数第一个
print('Item -2 is %s' % shoplist[-2]) # 打印:carrot 即倒数第二个
# Slicing on a list
print('Item 1 to 3 is %s' % shoplist[1:3]) # 打印:['mango', 'carrot'] 即下标[1]到[3],包括开始但不包括结束
print('Item 2 to end is %s' % shoplist[2:]) # 打印:['carrot', 'banana'] 即下标[2]到结束,包括最后一个
print('Item 1 to -1 is %s' % shoplist[1:-1]) # 打印:['mango', 'carrot'] 即下标[1]到[-1],包括开始但不包括结束
print('Item start to end is %s' % shoplist[:]) # 打印整个列表,跟直接写“shoplist”效果一样
# Slicing on a string (string与列表有同样的操作,)
name = 'swaroop'
print('characters 1 to 3 is %s' % name[1:3]) # 打印:wa
print('characters 2 to end is %s' % name[2:]) # 打印:aroop
print('characters 1 to -1 is %s' % name[1:-1]) # 打印:waroo
print('characters start to end is %s' % name[:]) # 打印:swaroop 跟直接写这个字符串一样
参考(引用)
当你创建一个对象并给它赋一个变量的时候,这个变量仅仅 参考 那个对象,而不是表示这个对象本身!
也就是说,变量名指向你计算机中存储那个对象的内存。
这被称作名称到对象的绑定。
例:
shoplist = ['apple', 'mango', 'carrot', 'banana']
mylist = shoplist # mylist 只是对象的另一个名称,他们指向相同的内存空间
del shoplist[0]
# 他们此时打印相同的内容,都少了'apple'
print('shoplist is', shoplist)
print('mylist is', mylist)
# 深拷贝,复制成另一个对象(得记住用切片操作符来取得拷贝)
mylist = shoplist[:] # make a copy by doing a full slice
del mylist[0] # remove first item
# 注意,现在他们打印出不同的内容
print('shoplist is', shoplist)
print('mylist is', mylist)
列表综合
通过列表综合,可以从一个已有的列表导出一个新的列表。
[返回值 for 元素 in 列表 if 条件] 比如 [num for num in xrange(100) if num%2==0] 返回0~99之间的偶数列表
# 例如,你有一个数的列表,而你想要得到一个对应的列表,使其中所有大于2的数都是原来的2倍。对于这种应用,列表综合是最理想的方法。
listone = [2, 3, 4]
listtwo = [2*i for i in listone if i > 2] # 为满足条件(if i > 2)的数指定了一个操作(2*i),从而导出一个新的列表。
print(listtwo) # 打印: [6, 8]
ls=[1,3,5,7] # reduce 在python3去掉了
print(reduce(lambda x,y:x+y,ls)) # 计算过程就是 1+3=4 然后4+5得到结果9,再加7,以此类推,最后返回最终计算的结果(总和);打印:16
# 将字典的key,value倒过来的写法:
a_dict = {'a': 1, 'b': 2, 'c': 3}
# python3 的写法:
b_dict = {value:key for key, value in a_dict.items()}
# python2 时的写法:
b_dict = {}
for key, value in a_dict.iteritems():
b_dict[value] = key
print(b_dict) # key与value翻转,打印: {1:'a', 2:'b', 3:'c'}
说明:
注意原来的列表并没有发生变化。
在很多时候,我们都是使用循环来处理列表中的每一个元素,而使用列表综合可以用一种更加精确、简洁、清楚的方法完成相同的工作。
小心 list 的 += 操作(python2时可以用,python3不可以再这样用)
集合
Python3 开始有这写法,跟之前的差不多,只是用大括号括起来,如: a = {1, 'aa', 3, 5, 6}
集合同样可以使用综合计算,如: a = {x for x in range(10) if x % 2 == 0}
成员测试 in, not in
检查是否包含有此内容,返回 True 或者 False, 例如:
# 1.对字符串
if 'a' in 'Swaroop':
print('Yes, it contains the string "a"')
# 2.对集合(列表、元组和字典)
if 'genre' in ('genre', 'jazz'):
print('Yes, it contains the genre')
print('genre' in ('genre', 'jazz')) # 元组,打印: True
print('genre' in ['genre', 'jazz']) # 列表,打印: True
print('genre' in {'genre':'sss', 'jazz':'dddd'}) # 字典,检查key,打印: True
print('sss' in {'genre':'sss', 'jazz':'dddd'}) # 字典,打印: False
排序
1.sort方法
Python语言内置了sort方法,可以很方便地对某个List进行排序
例如:
L = [6, 5, 1, 3, 4, 2]
L.sort()
print(L) # 打印:[1, 2, 3, 4, 5, 6]
li=[(2,'a'),(4,'b'),(1,'d')]
li.sort() # 元组列表排序
print(li) # 打印: [(1, 'd'), (2, 'a'), (4, 'b')]
2.自定义排序(例如,按关键词的权重排序,按人的年龄排序,等等)
若List中每个元素都是2-tuple,tuple中第一个元素为String类型的keyword,第二个元素为该字符串对应的权重(int类型),希望按照权重排序(从高到低),则可以这样:
L = [('b', 1), ('a', 0), ('c', 2), ('d', 3)]
# L.sort(lambda E1, E2: -cmp(E1[1], E2[1])) # cmp函数里面是需比较的两个值,负号表示倒序。(python2 的写法)
L.sort(key=lambda d:-d[1]) # Python3的写法,由于去掉了cmp()函数,得传入key参数; python2也可以这样用;负号表示倒序
print(L) # 打印:[('d', 3), ('c', 2), ('b', 1), ('a', 0)]
3.dict排序
对字典的排序,因为每一个项包括一个键值对,所以要选择可比较的键或值进行排序
sorted(iterable[, cmp[, key[, reverse]]])
# cmp 和 key 一般使用 lambda
如:
d={"ok":1,"no":2}
# 对字典按键排序,用元组列表的形式返回
print(sorted(d.items(), key=lambda a:a[0])) # 打印: [('no', 2), ('ok', 1)]
print(sorted(d)) # 打印:['no', 'ok']
print(d) # 原字典并未改变,打印:{'ok':1, 'no':2}
# 对字典按值排序,用元组列表的形式返回
print(sorted(d.items(), key=lambda d:d[1])) # 打印:[('ok', 1), ('no', 2)]
# 排序后再转成字典,就无法再保证排序了
b = sorted(d.items(), key=lambda v:v[0])
print(b) # 打印: [('no', 2), ('ok', 1)]
print(dict(b)) # (排序又乱了)打印: {'ok': 1, 'no': 2}
4.类的排序
class test:
def __init__(self,a,b):
self.a = a
self.b = b
test1 = test(5,25)
test2 = test(50,35)
test3 = test(10,15)
tests = [test1, test2, test3]
# 以 cmp 来指定排序方式, python3不可以这样写(没有cmp参数及cmp函数)
result = sorted(tests,cmp = lambda x,y: cmp(x.a, y.a))
# 遍历排序结果,结果是已排序的: a:5 a:10 a:50
for item in result:
print("a:%s" % item.a)
# 以 key 来排序,结果也是可以的
result2 = sorted(tests,key = lambda d:d.a)
for item in result2:
print("a:%s" % item.a)
# 遍历原资料,原资料的顺序没有改变
for item in tests:
print("a:%s" % item.a)
5.注意:
python3 由于去掉了 cmp() 函数,可以用“(a > b) - (a < b)”代替“ cmp(a, b) ”
6.冒泡算法,如下:
num = [23,2,3,6,18,9,33,13,24,19]
for i in range(len(num)-1):
for j in range(len(num)-i-1):
if (num[j] > num[j+1]):
num[j], num[j+1] = num[j+1], num[j] # 置换,这样写比较简便,不需再用临时变量
print(num)
综合实例:
在Python中对列表,元组,字典等内置的数据结构的处理是很方便的事情,python借鉴了Lisp中的很多函数式计算的方法来处理列表,可以极大的简化我们的代码。
1. set(): 将元组,列表 转化成没有重复项的集合
2. list(): 将集合,元组转化成列表
3. tuple(): 将集合,列表转化成元组
4. map(func,list):将list的每一个元素传递给func的函数,这个函数有一个参数,且返回一个值,map将每一次调用函数返回的值组成一个新列表返回
5. filter(func,list):将list的每一个元素传递给func的函数,这个函数有一个参数,返回bool类型的值,filter将返回True的元素组成新列表返回
6. reduce(func,list):将list的元素,挨个取出来和下一个元素通过func计算后将结果和再下一个元素继续计算
一、列表去重
ls = [1,3,2,5,2,1,3,4,6]
ls = list(set(ls)) # 最简单的列表去除重复
L = [1, 8, 3, 4, 6, 2, 3, 4, 5]
kk = [x for x in L if x not in locals()['_[1]']] # 保留原顺序的去除重复,只有 2.6 上可以, 2.7 以上版本不能这样写
# '_[1]' 是个内部临时变量,可查看: [x for x, y in locals().items()]
二、假如有列表:
books = [
{"name":"C#从入门到精通", "price":23.7, "store":"卓越"},
{"name":"ASP.NET高级编程", "price":44.5, "store":"卓越"},
{"name":"C#从入门到精通", "price":24.7, "store":"当当"},
{"name":"ASP.NET高级编程", "price":45.7, "store":"当当"},
{"name":"C#从入门到精通", "price":26.7, "store":"新华书店"},
{"name":"ASP.NET高级编程", "price":55.7, "store":"新华书店"},
]
2.1 求《ASP.NET高级编程》价格最便宜的店:
storename=min([b for b in books if b['name']=="ASP.NET高级编程"],key=lambda b:b['price'])["store"]
过程:先用列表解析取出《ASP.NET高级编程》的列表,通过min函数,比较字典的price键获取price最小的项
2.2 求在新华书店购买两本书一样一本要花的钱:
price=sum([b['price'] for b in books if b['store']=="新华书店"])
2.3 求列表中有那几本书:
booknames=list(set([b['name'] for b in books]))
2.4 列表里的书都打5折:
books=map(lambda b:dict(name=b['name'],price=b['price']*0.5,store=b['store']),books)
2.5 《C#从入门到精通》的平均价格:
avg=(lambda ls:sum(ls)/len(ls))([b['price'] for b in books if b['name']=="C#从入门到精通"])
2.6 求每本书的平均价格:
book_avg=map(lambda bookname:dict(name=bookname,avg=(lambda ls:sum(ls)/len(ls))([b['price'] for b in books if b['name']==bookname])),list(set([b['name'] for b in books])))
这段代码放在一行比较难看懂,但是格式化一下就很好懂了,构建的过程如下:
step1: 要求每本书的平均价格,首先要得到共有几本书,方法见2.3,得到去重的书名列表
list(set([b['name'] for b in books])) #去重后的书名列表
step2: 要求每一本书的均价,需要将计算均价的函数映射到每一本书上,于是
map(
#计算均价的函数,
list(set([b['name'] for b in books])) #去重后的书名列表
)
step3: 加入计算单本书均价的函数,参考2.5的方法,由于只用一行,所以用lambda来搞定:
func=lambda bookname:(lambda ls:sum(ls)/len(ls))([b.price for b in books if b['name']==bookname])
step4: 将计算单本均价的lambda函数加入map中,得到最终结果:
经过格式化后的结果,前面的单行代码可以格式化为下面容易阅读的形式
book_avg=map(
lambda bookname:
dict(
name = bookname,
# 计算单本书均价的函数
avg = (lambda ls:sum(ls)/len(ls)) ([b['price'] for b in books if b['name']==bookname])
),
#去重后的书名列表
list(
set(
[b['name'] for b in books]
)
)
)
在函数中接收元组和列表(函数的参数数量可以变动,即可变长参数)
当要使函数接收元组或字典形式的参数的时候,有一种特殊的方法,它分别使用*和**前缀。
这种方法在函数需要获取可变数量的参数的时候特别有用。
而且,使用*和**前缀的参数还可以传递给其它函数。
例:
# 由于在args变量前有*前缀,所有多余的函数参数都会作为一个元组存储在args中
def sum(message, *args):
'''Return the sum of each argument.'''
total = 0
# 除了用循环,也可以用下标来读取参数,如: args[0]
for i in args:
total += i
print (str(type(args)) + ' ' + message + ":" + str(total))
sum2(args) # 这样传过去的 args 是一个元组;打印如: ((3, 5.5),)
sum2(*args) # 这样传过去的 *args 表示多个参数;打印如:(3, 5.5)
def sum2(*args):
print(args)
sum('hight', 3, 5.5) # 打印: <type 'tuple'> hight:8.5
sum('weight', 10) # 打印: <type 'tuple'> weight:10
# 函数参数接收字典用法。使用的是**前缀,多余的参数则会被认为是一个字典的键/值对。
def printDict(message, **args):
print(str(type(args)) + ' ' + message + ':' + str(args))
printDict2(args = args) # 可这样,把 args 当做一个值(里面是字典),传过去;打印如: {'args': {'a': 3, 'b': 'dd'}}
printDict2(**args) # 也可这样,把 **args 看做传过来的多个键/值对,传过去;打印如:{'a': 3, 'b': 'dd'}
def printDict2(**args):
print(args)
# 注意:参数为字典时,参数里面必须使用等号,否则运行出错
printDict('hight', a=3, b='dd') # 打印: <type 'dict'> hight:{'a': 3, 'b': 'dd'}
# 可以混合使用*和**前缀的参数, 但是必须 *args 在前, **args 在后,否则编译不通过
def printMul(message, *args1, **args2):
print(message + ' args1:' + str(args1) + ' args2:' + str(args2))
printMul('hello', 5, 4, a=2, b=3) # 打印: hello args1:(5, 4) args2:{'a': 2, 'b': 3}
面向对象的编程
面向过程的编程:根据操作数据的函数或语句块来设计程序的。
面向对象的编程:把数据和功能结合起来,用称为对象的东西包裹起来组织程序的方法。
类和对象是面向对象编程的两个主要方面。“类”创建一个新类型,而“对象”是这个类的实例。
域:属于一个对象或类的变量。
方法:属于类的函数,被称为类的方法。
域和方法可以合称为类的属性。
域有两种类型——属于每个实例/类的对象或属于类本身。它们分别被称为实例变量和类变量。
类使用class关键字创建。类的域和方法被列在一个缩进块中。