您的位置:首页 > 编程语言 > Python开发

python学习笔记

2015-10-20 20:07 811 查看
python学习2.7或者是3.3

1.python 中的三种引号,单引号,双引号,三引号,“"",其实作用是一样的,在引号嵌套中可以体现,三引号可以自动分行同\n的作用

2.print("")

3.数值类型:整数,浮点型、复数(12+j,12j+1)

4.python文件编写的源码的后缀是以.py结束的。

部分例子

print("this is my python program");

print("we will learn well!");

print('this is my first code python');

print("""this

is

my first

program """);

"123"+"456";

print("123","456");

"hello %s" % ("liming");

print("hello %s" % ("liming"));

5.python中显示数值类型是,不能使用+,应为+对应于两个可以兼容的对象类型实现的,""+123,一个是字符串,另一个是数字,因此是不可以的

可以使用str(),或者类似这种形式"this float data %%f: %f" % 5.43. "this is num "+str(4)

6.当python在进行数值运算时,如果超过范围将会显示inf,infinity(无穷大)

7.在python3.1之前版本,整数除法一般是不显示小数的,在该版本及其以后,可以显示,也可以通过设置让其不显示.

8.python取余运算符,% 100%3=1 100.0%3.0=1.0

9.在python3.1或者之前可能会有

4023-22.4

显示>>>4000.5999999999999

print("%f" % (4023-22.4))

显示>>>4000.600000

print("%.2f" % (4023-22.4))

小数点后取两位,最后一位四舍五入

但是在python3.3.4中显示4000.6,这是版本进化中的改进.

10.8进制和16进制显示

"hello %s" % ("liming");

print("hello %s" % ("liming"));

print("%o %o %o %o %o %o %o %o %o " % (6,7,8,9,10,11,12,13,14));

print("%x %x %x %x %x %x %x %x" % (9,10,11,12,13,14,15,16)) ;

11.python 中的print传递参数时有点和c不太一样,print("" % () );参数放到里面的括号里,中间用逗号隔开

12.python(字符串、数值)还提供了另外4种基本重要的类型:元组、列表、集合、字典。

元组:tuple类似于数组,他们被圆括号包围,元组的内容不能改变("is","hello","kitty","mimi")

filler = ("string","filler","as","tuple");

print(filler);

('string', 'filler', 'as', 'tuple')

可以通过类似于数组的下标来访问如filler[0]

('string', 'filler', 'as', 'tuple')

>>> filler = ('string', 'filler', 'as', 'tuple')

>>> filler[0]

'string'

>>> filler[3]

'tuple'

可以通过内置函数获得元组中数据的多少len(filler) =4

创建包含一个元素的元组

a=("123",);len(a)=1;如果是这样的话:a=("123") ,,len(a) =3,a[0]=1,相当于访问的是对应该字符串的字符数组

一个元组包含另外一个元组

a=("123",'456',"""789""","0");

b=(a,"abc");

>>>len(b) =2

>>>b[0] =("123","456","789","0")

>>>b[0][0]="123"

(2)列表

列表如同元组,是包含从0开始引用的元素的序列,列表用方括号创建,可以用下标取值,并且值可以改变,不能直接用列表名输出列表中各个元素

breakfast =["123","456","789","0"],

breakfast ,print(breakfast)

len(breakfast) =4,breakfast[0] ="123";breakfast[0]="0123",0位置的元素就变成了0123

breakfast.append("abc");向列表最后位置添加元素

breakfast.extend(["absd","sfd","mcf","dfg"]);列表中添加新的列表,添加后显示的是每个元素都会添加到原来的列表中,和元组中添加新的元组有些不同

(3)字典

字典类似于列表和元组。他是包含一组数据的另外一种容器。然而元组和列表以数据顺序索引,字典却用选择的名称索引

字典用花括号创建{},其内容就是键值对的形式存放。

menus_specials = {};初次赋值花括号创建一个空字典,一旦空字典被定义并且通过名称引用,将开始使用如下方式对其实例初始化;

将希望作为索引的名称放在方括号内,将通过该索引引用的值放在等号的右端

menus_specials["breakfast"] = "Canadian ham";

menus_specials["lunch"] = "tuna surprise";

menus_specials["dinner"] = "Cheeseburger Deluxe";

例子:

>>> menus_specials = {};

>>> menus_specials["breakfast"] = "Canadian ham";

>>> menus_specials

{'breakfast': 'Canadian ham'}

。索引名称叫键,对应的值叫做值。如果直接在{}中定义键值对,键值中间用冒号,

一个键值对后用逗号分隔如

>>> abs_menus={"1":"china","2":"america"}

>>> abs_menus

{'1': 'china', '2': 'america'}

>>> abs_num={"a1":1,"a2":2};

>>> abs_menus["1"]

'china'

>>> abs_num

{'a1': 1, 'a2': 2}

>>> abs_mixed={"a1":1,"a2":"bb"};值中放置的数据类型格式不一致也可以,如下

>>> abs_mixed

{'a1': 1, 'a2': 'bb'}

从字典中取值,只需要字典名称[键],键维字符串的,用字符串格式

>>> num_int = {1:1,2:2};

>>> num_int[1]

1

>>>

从字典中获取键、值

字典名.keys();字典名.values();list(...)列出每个内容

//python编程入门。pdf 56页

key_list = menu_specials.keys();

print(list(key_list));

menu_specials.get("lunch");通过键获得一个值.

如果插入了相同的键,将会把之前的值给替换掉.

12.对于字符串,可以当成字符列表表示。

13.python中几种特殊的类型:None,True,False;None应该与我们见过的Null类似,后面两个是布尔真值真和假

True==1 为True, False==0 为True

59页。

3.3序列的其他共有属性

字典没有序列从头至尾的顺序排列,字典是无序的。

元组和列表都是一种序列。

在序列中访问序列的后面的元素,可以通过[-1]访问最后一个元素,[-2]访问倒数第二个元素,如:

last_names =["simida","shayangnala","nihao","hello"];

>>> len(last_names)

4

>>> print("%s" % last_names[3])

hello

>>> print("%s" % last_names[-1])

hello

>>> print("%s" % last_names[-2]);

nihao

注意这里的序列名称不要输错了,不然的话会提示错误的哦。

13.序列的范围 可以获取序列的一部分,从中提取一个片段,创建可以单独使用的一个副本。创建这些分组的方法叫做分片。

>>> slice_me =("the","next","time","we","meet","drinks","are","on","me","ok");

>>> sliced_tuple = slice_me[5:9];

>>> print(sliced_tuple);

('drinks', 'are', 'on', 'me')

从0开始计数,下标5位置开始(包括),下标9位置结束(不包含结尾);注意使用了[5:9]

>>> slice_this_list = ["the","next","time","we","meet","drinks","are","on","me","ok"];

>>> sliced_list = slice_this_list[5:9];

>>> print(sliced_list);

['drinks', 'are', 'on', 'me']

>>> string_list= "the next time we meet drinks are on me ok";

>>> string_list_sliced=string_list[5:9];

>>> print(string_list_sliced);

ext

注意上面ext后面有个空格。总之在每种情形下,用冒号指定一序列的一个片段指示python创建一个新的序列,新序列恰好包含了片段中的元素。

14.序列两个序列合并

living_room =("rug","table","chair","TV","dustbin","shelf");

apartment=[];

apartment.append(living_room)

apartment

这样只是在序列中添加了分层[('rug', 'table', 'chair', 'TV', 'dustbin', 'shelf')]

apartment[0] ('rug', 'table', 'chair', 'TV', 'dustbin', 'shelf')

因此该种方法只是添加分层,并没有真正合并。

应该使用extend方法,实现两个序列合并到一个序列上

>>> apartment.extend(living_room)

>>> apartment

['rug', 'table', 'chair', 'TV', 'dustbin', 'shelf']

15.使用列表放置临时数据,处理完的数据可以pop出去,避免列表的笨重

>>> todays_temperatures = [23,32,33,31]

>>> todays_temperatures.append(29)

>>> todays_temperatures

[23, 32, 33, 31, 29]

>>> morning= todays_temperatures.pop(0)

>>> morning

23

>>> todays_temperatures

[32, 33, 31, 29]

如果没有指定pop删除的元素,他将删除最后一个元素

>>> todays_temperatures

[32, 33, 31, 29]

>>> last = todays_temperatures.pop()

>>> last

29

>>> todays_temperatures

[32, 33, 31]

16.处理集合

在Python中,集合与字典类似,只是它进包含键,而没有雨键相关联的值。本质上,集合是不包括重复数据的数据集。在从数据集删除重复数据时,

集合非常有用。

集合种类有两种:可变集合与不可变集合(frozenset).可变集合可以增加、删除、改变元素;不可变集合的元组在他们被出示设定之后就不能再被修改。

>>> alphabet=['a','b','c','d','d','a','f','m']

>>> print(alphabet)

['a', 'b', 'c', 'd', 'd', 'a', 'f', 'm']

>>> len(alphabet)

8

>>> alph2=set(alphabet)

>>> alph2

{'d', 'f', 'a', 'b', 'c', 'm'}

>>> alph3 = frozenset(alphabet)

>>> alph3

frozenset({'d', 'f', 'a', 'b', 'c', 'm'})

可以看出可变集合与不可变集合都会把重复的元素去掉。set()之后的返回的集合不准修改其中元素的内容。

17.

>>> a=['a','b']

>>> c=['c','d']

>>> mm=(a,c)

>>> mm

(['a', 'b'], ['c', 'd'])

>>> a1=mm[0]

>>> a1

['a', 'b']

>>> a1[0]='v'

>>> a1

['v', 'b']

>>> mm

(['v', 'b'], ['c', 'd'])

元组是从0开始以固定数值顺序索引的一个数据序列。元组中的引用在元组被创建后不能再改变,也不能在增加或者删除元素。然而,如果数组包含可变元素的数据类型,

如列表,该数据类型的元素是可以改变的。直接把数据放到元组中,是不会改变的。

列表是另一种序列,除了他的元素可被修改之外,他与元组类似。列表的长度可以改变,以容纳使用append方法新增的元素,另外可以通过pop方法

所见列表的长度。如果希望一个序列中的数据附加到一个列表中,可以使用列表的extend方法一次性将序列中的所有元素添加到列表中。

字典是使用一种索引的数据分组。列表和元组以数值为索引,而字典通过所选的值索引。通过keys()方法获得所有键,values()获得值。他们都返回列表。

集合是项集(0个或者多项),不允许包含重复的值。

17.真值比较

>>> a='123456',b='34556'

SyntaxError: can't assign to literal

>>> a='122344';b='fsfs2234';

>>> a[1:5]==b[4:7]

False

>>> a[1:5]

'2234'

>>> b[4:8]

'2234'

>>> a[1:5]==b[4:8]

True

>>>

序列也可以用双等号比较,只要相同位置元素相同,就为True;字典也可以,是要相同位置上的键和值都相等,即可。

< > != == not(取反操作) and or

字符串中将字符全部转化为大写或者小写 lower(),upper() "absDf".lower()="absdf"

18.条件判断if ...:

if 和:中间的内容是相应的条件,同时if下面的内容没有end结束,他是以空格缩进为判断条件的,因此更要确定好缩进的格数。

>>> omelet_ingredients={"egg":2,"mushroom":5,"pepper":1,"cheese":1,"milk":1};

>>> fridge_contents ={"egg":10,"mushroom":20,"pepper":3,"cheese":2,"tomato":4,"milk":15};

>>> have_ingredients=[False]

>>> if fridge_contents["egg"]>omelet_ingredients["egg"]:

have_ingredients[0] =True

have_ingredients.append("egg")

SyntaxError: unindent does not match any outer indentation level

>>> if fridge_ingredients["egg"]>omelet_ingredients["egg"]:

have_ingredients[0] = True

have_ingredients.append("egg")

Traceback (most recent call last):

File "<pyshell#89>", line 1, in <module>

if fridge_ingredients["egg"]>omelet_ingredients["egg"]:

NameError: name 'fridge_ingredients' is not defined

>>> if fridge_contents["egg"]>omelet_ingredients["egg"]:

hava_ingredients[0] =True

have_ingredients.append("egg")

Traceback (most recent call last):

File "<pyshell#93>", line 2, in <module>

hava_ingredients[0] =True

NameError: name 'hava_ingredients' is not defined

>>> if fridge_contents["egg"]>omelet_ingredients["egg"]:

have_ingredients[0] =True

have_ingredients.append("egg")

>>> print(have_ingredients)

[True, 'egg']

>>> if fridge_contents["mushroom"]>omelet_ingredients["mushroon"]:

if hava_ingredients[0]==False

SyntaxError: invalid syntax

>>> if fridge_contents["mushroom"]>omelet_ingredients["mushroon"]:

if have_ingredients[0] ==False:

have_ingredients[0] =True;

have_ingredients.append("mushromm");

Traceback (most recent call last):

File "<pyshell#105>", line 1, in <module>

if fridge_contents["mushroom"]>omelet_ingredients["mushroon"]:

KeyError: 'mushroon'

>>> if fridge_contents["mushroom"] >omelet_ingredients["mushroom"]:

if have_ingredients[0] ==False

SyntaxError: invalid syntax

>>> if fridge_contents["mushroom"] >omelet_ingredients["mushroom"]:

if have_ingredients[0] ==False:

have_ingredients[0] = True

have_ingredients.append("mushroom")

>>> print(have_ingredients)

[True, 'egg', 'mushroom']

注意别输错了键值,不然会像我那样报错的偶。

>>> if fridge_contents["pepper"]>omelet_ingredients["pepper"]:

if have_ingredients[0] ==True:

have_ingredients[0] = False;

have_ingredients.append("pepper")

>>> if fridge_contents["cheese"]>omelet_ingredients["cheese"]:

if have_ingredients[0]==False:

have_ingredients[0]=True

have_ingredients.append("cheese")

>>> if fridge_contents["milk"]>omelet_ingredients["milk"]:

if have_ingredients[0]==True:

have_ingredients[0]=False

have_ingredients.append("milk")

>>> if have_ingredients[0]==True:

print("I have the ingredients to make an omelet!")

>>> if have_ingredients[0]==False:

print("i don\'t have the ingredients to make an omelet!")

i don't have the ingredients to make an omelet!

if ...:

....

elif ..:

...

elif ..:

...

这就是if,else的多种选择方式。注意嵌套式空格数要对其,python是以空格数来判断模块的。

其实最后可以放一个else:,来对于所有的条件都不满足的情形。

milk_price = 1.50

>>> if milk_price<1.25:

print("buy two cartons of milk ,they're on sale")

elif milk_price<2.00:

print("buy one carton of milk ,prices are normal")

elif milk_price>2.00:

print("go somewhere else! milk costs too much here")

buy one carton of milk ,prices are normal

>>> OJ_price = 2.50;

>>> if OJ_price<1.25:

print("get one ,i'm thirsty")

elif OJ_price<=2.00:

print("ummm, sure, but i'll drink it slowly.")

else:

print("i don't have enough money. nerver mind")

i don't have enough money. nerver mind

嵌套if

if milk_price<1.25:

if OJ_price<1.25:

print("milk ,i'm thirsty")

elif OJ_price<=2.00:

print("milk ,drink slowly")

else:

print("milk, i not have enough money")

elif milk_price>2.00:

if OJ_price<2.00:

print("milk ,ummm")

else:

print("milk , i run")

else:

print("milk ,robust i can not get ")

19循环

while ...:。 for ...int ...:。

while i>0:

print("%%d:%d" % i)

i=i-1

for i in range(10,0,-1):

print("%d" % i)

10

9

8

7

6

5

4

3

2

1

in 后面的为一个序列获得是集合

while True:

print("infinty operate")

例子:

>>> age =0

>>> while True:

how_old=input("Enter your age: ")

if how_old=="No":

print("dont be ashamed of your age")

break

num=int(how_old)

age=age+num

print("your age is : ")

print(age)

print("that is old")

Enter your age: 1

your age is :

1

that is old

Enter your age: 2

your age is :

3

that is old

Enter your age: -3

your age is :

0

that is old

Enter your age: 50

your age is :

50

that is old

Enter your age: No

dont be ashamed of your age

break ,continue仍然和以前遇到的结束循环的状态是一致的.

>>> for food in ("pate","cheese","rotten apples","crackers","whip cream","tomato soup"):

if food[0:6]=="rotten":

continue

print("hey, you can eat %s" % food)

hey, you can eat pate

hey, you can eat cheese

hey, you can eat crackers

hey, you can eat whip cream

hey, you can eat tomato soup

20.异常处理 try: excep ExceptionType:例子如下

fridge_contents={"egg":8,"mushroom":20,"pepper":3,"cheese":2,"tomato":4,"milk":13}

>>> try:

if fridge_contents["orangenjuice"]>3:

print("sure ,let us have some juice")

except KeyError:

print("Awww, there is no juice. let to shopping")

21.函数

定义的函数运行,在cmd下,需要到该目录下面()注意需要在环境变量中配置python,然后python -i filename.py

另外一种是直接通过python的GUI,选择运行,即可.

#!/usr/bin/env python3.3

def in_fridge():

"""This is a function to see if the fridge has a food.

fridge has to be a dictionary defined outside of the function.

the food to be searched for is in the string wanted_food"""

try:

count = fridge[wanted_food]

except KeyError:

count = 0

return count

函数定义如上,里面用的变量,函数创建一个新的空间,其中名称可以被重新使用和创建,而不会影响到程序

的其他作用域中的相同名称。

输出函数的注释部分,doc前后都是两个下划线

>>> print("%s" % in_fridge.__doc__)

This is a function to see if the fridge has a food.

fridge has to be a dictionary defined outside of the function.

the food to be searched for is in the string wanted_food

>>>

dir()

>>> dir()

['__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', 'fridge', 'in_fridge', 'wanted_food']

可以显示出我们使用的所有的属性。

22.函数作用域,最上面一层作用域中的任何名称在一个底层次作用域中可以再次被使用,而不影响上层名称引用的数据。

>>> special_sauce=['ketchup','mayonnaise','french dressing']

>>> def make_new_sauce():

"""this function makes a new special sauce all its own """

special_sauce=["mustard","yogurd"]

return special_sauce

>>> print("%s" % special_sauce)

['ketchup', 'mayonnaise', 'french dressing']

>>> new_sauce = make_new_sauce()

>>> print("%s" % special_sauce)

['ketchup', 'mayonnaise', 'french dressing']

>>> print(new_sauce)

['mustard', 'yogurd']

23.注释#,不在字符串中出现,

#this is comment

注释的位置放置需要特别注意,不然会被当成缩进的形式,而提前结束已成型的代码(因为加入了注释)

带参数的函数

#!/usr/bin/env python3.3

def in_fridge2(some_fridge,desired_item):

"""this is a function to see if the fridge has a food .

fridge has to ne a dictionary defined outside of the function.

the food to be searched for is in the string wanted_food"""

try:

count = some_fridge[desired_item]

except KeyError:

count =0

return count

>>> fridge={'apples':2,'oranges':3}

>>> desired_item='apples'

>>> in_fridge2(fridge,desired_item)

2

24.python是一种类似于java的先编译,后解释的语言。先编译成(由高级语言编译成某一种中间代码),然后又python解释器解释执行。

python源文件后缀是.py,pyc,而PyCodeObject文件则是Python编译器真正编译成的结果。当python程序运行时,编译的结果则是保存在位于内存中的

PyCodeObject中,当Python程序运行结束时,Python解释器将PyCodeObject写回到pyc文件中。当python程序第二次运行时,首先会在硬盘中找寻pyc文件。

如果找到直接载入,否则重复上面过程。

25.使用type()确定类型

>>> fridge={"apples":10,"oranges":3,"milk":2}

>>> type(fridge)

<class 'dict'>

>>> type({})

<class 'dict'>

>>> type("omelet")

<class 'str'>

>>> type("")

<class 'str'>

>>>

可以使用str()将内容转换成字符串来比较,注意使用str与不适用str时的输出内容的区别。

>>> fridge_type = str(type(fridge))

>>> fridge_type

"<class 'dict'>"

>>> if fridge_type=="<class 'dict'>":

print("they match")

they match

26.带有默认值的函数,def make_omelet2(omelet_type="cheese"):该定义并不改变函数其余代码的行为。他仅仅在函数make_omelet2被调用,但没有定义

omelet_type时设置它的值。

如果编写了一个有多个参数的函数,并且希望其中既有必须参数也有可选参数,必须将可选参数放在参数列表的末尾。因为一旦指定某个参数为可选参数,

他可额能出现也可能不出现。第一个默认参数后面的所有参数都变成可选参数。

#! /usr/bin/env python3.3

def print_du(name,age=10):

"""this function is a example of maybe selected parameter."""

print("%s , %d" % (name,age))

默认值的参数放到最右边。

27.函数调用函数,将所有函数统一写在一个文件中,并在命令行中cd到该文件夹下,运行

#! /usr/bin/env python3.3

def make_omelet(omelet_type):

"""this will make an omelet.You can either pass in a dictionary

that contains all of the ingredients for your omelet,or provide a string

to select a type of omelet this function already knows about """

if type(omelet_type)==type({}):

print("omelet_type is a dictionary with ingredients")

return make_food(omelet_type,"omelet")

elif type(omelet_type)==type(""):

omelet_ingredients = get_omelet_ingredients(omelet_type)

return make_food(omelet_ingredients,omelet_type)

else:

print("i dont not think i can make this kind of omelet: %s" % omelet_type)

def get_omelet_ingredients(omelet_name):

"""This contains a dictionary of omelet names that can be produced,

and their ingredients"""

#All of our omelets need eggs and milk

ingredients ={"eggs":2,"milk":1}

if omelet_name=="cheese":

ingredients["cheddar"] =2

elif omelet_name=="western":

ingredients["jack_cheese"] =2

ingredients["ham"] =1

ingredients["pepper"] = 1

ingredients["onion"] =1

elif omelet_name=="greek":

ingredients["feta_cheese"]=2

ingredients["spinach"] =2

else:

print("that\'s not on the menu ,sorry! ")

return None

return ingredients

def make_food(ingredients_needed,food_name):

"""make_food (ingredients_needed,food_name)

takes the ingredients from ingredients_needed and makes food_name"""

for ingredients in ingredients_needed.keys():

print("Adding %d of %s to make a %s " % (ingredients_needed[ingredients],ingredients,food_name))

print("Made %s " % (food_name))

return food_name

#

>>> omelet_type = make_omelet("cheese")

Adding 2 of cheddar to make a cheese

Adding 1 of milk to make a cheese

Adding 2 of eggs to make a cheese

Made cheese

>>> omelet_type = make_omelet({"eggs":2,"jack_cheese":2,"milk":1,"mushroons":10})

omelet_type is a dictionary with ingredients

Adding 2 of jack_cheese to make a omelet

Adding 1 of milk to make a omelet

Adding 10 of mushroons to make a omelet

Adding 2 of eggs to make a omelet

Made omelet

>>>

27.函数中嵌套函数

内部嵌套的函数级别和外面的函数相同,注意嵌套函数的缩进(嵌套函数定义缩进与被嵌套函数缩进一致,嵌套内部函数缩进统一);同时要在该函数调用它之前定义它。

#! /usr/bin/env python3.3

def make_omelet(omelet_type):

"""this will make an omelet.You can either pass in a dictionary

that contains all of the ingredients for your omelet,or provide a string

to select a type of omelet this function already knows about """

def get_omelet_ingredients(omelet_name):

"""This contains a dictionary of omelet names that can be produced,

and their ingredients"""

#All of our omelets need eggs and milk

ingredients ={"eggs":2,"milk":1}

if omelet_name=="cheese":

ingredients["cheddar"] =2

elif omelet_name=="western":

ingredients["jack_cheese"] =2

ingredients["ham"] =1

ingredients["pepper"] = 1

ingredients["onion"] =1

elif omelet_name=="greek":

ingredients["feta_cheese"]=2

ingredients["spinach"] =2

else:

print("that\'s not on the menu ,sorry! ")

return None

return ingredients

if type(omelet_type)==type({}):

print("omelet_type is a dictionary with ingredients")

return make_food(omelet_type,"omelet")

elif type(omelet_type)==type(""):

omelet_ingredients = get_omelet_ingredients(omelet_type)

return make_food(omelet_ingredients,omelet_type)

else:

print("i dont not think i can make this kind of omelet: %s" % omelet_type)

def make_food(ingredients_needed,food_name):

"""make_food (ingredients_needed,food_name)

takes the ingredients from ingredients_needed and makes food_name"""

for ingredients in ingredients_needed.keys():

print("Adding %d of %s to make a %s " % (ingredients_needed[ingredients],ingredients,food_name))

print("Made %s " % (food_name))

return food_name

if type(omelet_type)==type({}):

print("omelet_type is a dictionary with ingredients")

return make_food(omelet_type,"omelet")

elif type(omelet_type)==type(""):

omelet_ingredients = get_omelet_ingredients(omelet_type)

return make_food(omelet_ingredients,omelet_type)

else:

raise TypeError("no such omelet type: %s" % omelet_type)

最后一句将打印错误替换为raise...语句,这样既可以通过函数处理错误,也可以将该错误打印出来。显示错误提示信息。

28.106

类的创建 class classname:

class Fridge:

"""This class implements a fridge where ingredients can by added and removed individually,or in groups."""

这种形式和函数等定义类似

创建的空类可以通过命令行向里面添加东西,如下操作

>>> f = Fridge()

>>> f.itams=[]

>>> f.itams["mystery meat"] =1

Traceback (most recent call last):

File "<pyshell#2>", line 1, in <module>

f.itams["mystery meat"] =1

TypeError: list indices must be integers, not str

>>> f.itams.append("abs")

>>> f.items={}

>>> f.items

{}

>>> f.items["mystery meat"]=1

>>> f.items

{'mystery meat': 1}

>>>

对象提供给外界使用的方法叫做接口,因为这些方法是 对象之外的程序使用该对象的途径。对象通过提供接口变得使用。

接口是使对象可用的任何方法和名称。在Python中,这通常意味着没有以一个或多个下划线开头的方法和名称都是接口;当然,

在类的文档字符串中明确指出哪些方法可用,以及如何使用它们,以与那些不希望被调用的函数区别。

class Fridge:

"""This class implements a fridge where ingredients can be

added and removed individually,or in groups.

The Fridge will retain a count of every ingredient added or removed,

and will raise an error if a sufficient quantity of an ingredient

isn't present.

Methods:

has(food_name [,quantity]) - checks if the string food_name is in the fridge.

Quantity will be set to 1 if you don't specify a number.

has_various(foods) - checks if enough of every food in the dictionary is in

the fridge

add_one(food_name) - adds a single food_name to the fridge

add_many(food_dict) -adds a whole dictionary filled with food

get_one(food_name) -takes out a single food_name from the fridge

get_many(food_dict) - takes out a whole dictionary worth of food.

get_ingredients(food) - If passed an object that has the __ingredients__method,

get_many will invoke this to get the list of ingredients.

"""

def __init__(self,items={}):

"""Optionally pass in an initial dictionary of items"""

if type(items)!==type({}):

raise TypeError("Fridge requires a dictionary but was given %s" % type(items))

self.items = items

return

从上面可以看出,对于类进行说明,这是很重要的,而且在写之前就需要详细的确定好需要定义的类,函数等;此外__init__函数不是接口,self;这两个

是类的两个非常重要的特征。当PYthon创建对象时,__init__方法传递给对象第一个参数
。而self实际上市代表该实例本身的变量。(相当于java里面的this)

另外,当决定编写一个类时,为希望使用的方法做注释是一个好习惯。实际上,它是考虑类的信息的完整性,类要完成的功能的概述。这使得

在编写程序的同时就可以测试程序。

当编写接口方法时,将会注意到,大多数情况下,简单的方法共享许多特征,但是为了使他们调用起来比较简单,希望保留各种形式。然而,不用

重复输入接口方法的共同部分,可以编写仅由每个方法内部使用的私有方法二节省输入。

这些私有方法可以执行部分或者全部接口方法的共同操作。当私有方法很复杂,或者包含用户在使用方法时不需要了解细节时,需要进行这样的操作。

虽然Python函数的参数没有指明类型,但是在函数内部确实是通过了一些验证的手段来进行类型的验证,以确保传入数据格式的正确性。

class Fridge:

"""This class implements a fridge where ingredients can be

added and removed individually,or in groups.

The Fridge will retain a count of every ingredient added or removed,

and will raise an error if a sufficient quantity of an ingredient

isn't present.

Methods:

has(food_name [,quantity]) - checks if the string food_name is in the fridge.

Quantity will be set to 1 if you don't specify a number.

has_various(foods) - checks if enough of every food in the dictionary is in

the fridge

add_one(food_name) - adds a single food_name to the fridge

add_many(food_dict) -adds a whole dictionary filled with food

get_one(food_name) -takes out a single food_name from the fridge

get_many(food_dict) - takes out a whole dictionary worth of food.

get_ingredients(food) - If passed an object that has the __ingredients__method,

get_many will invoke this to get the list of ingredients.

"""

def __init__(self,items={}):

"""Optionally pass in an initial dictionary of items"""

if type(items)!=type({}):

raise TypeError("Fridge requires a dictionary but was given %s" % type(items))

self.items = items

return

#the docstring and intervening portions of the class would be here ,and

#__add_multi should go afterwards.

def __add_multi(self,food_name,quantity):

"""__add_multi(food_name,quantity) -adds more than one of a food item.

returns the number of items added

This should only be used internally,after the type checking has been done"""

if(not food_name in self.items):

self.items[food_name]=0

self.items[food_name] = self.items[food_name] +quantity

def add_one(self,food_name):

"""add_one(food_name) -adds a single food_name to the fridge

reutn True

raise a TypeError if food_name is not a string."""

if type(food_name)!=type(""):

raise TypeError("add_one requires a string ,given a %s" % type(food_name))

else:

self.__add_multi(food_name,1)

return True

def add_many(self,food_dict):

"""add_many(food_dict) -adds a whole dictionary filled with food as keys and quantitiea as values.

returns a dictionary with the removed food

raises a TypeError if food_dict is not a dictionary

return False if there is not enough food in the bridge."""

if type(food_dict)!=type({}):

raise TypeError("the input food_dict type %%" % type(food_dict))

for item in food_dict.keys():

self.__add_multi(item,food_dict[item])

def has(self,food_name, quantity=1):

"""

has (food_name,[quantity])-checks if the string food_name is in the fridge .Quantity defaults to 1

returns True if there is enough ,False otherwise."""

if type(food_name)!=type(""):

raise TypeError("food_name type has excep %s" % type(food_name))

if (not food_name in self.items):

return False

elif self.items[food_name]>=1:

return True

else:

return False

def has2(self,food_name,quantity=1):

"""has2(food_name,quantity)-checks if the string food_name in the fridge .Quantity defaults to 1

return True if there is enough ,False otherwise."""

if type(food_name)!=type(""):

raise TypeError("has type error %s " % type(food_name))

return self.has_various({food_name:quantity})

def has_various(self,foods):

"""has_various(foods) determines if the dictionary food_name

has enough of every element to satisfy a request.

return True if there is enough ,False if ther is not or if an element does not exist"""

if type(foods)!=type({}):

raise TypeError("foods has error %s" % type(foods))

for item in foods.keys():

if ( not item in self.items):

return False

elif foods[item]<self.items[item]:

return True

else:

return False

def __get_multi(self, food_name, quantity):

"""

__get_multi(food_name, quantity) -removes more than one of a food item .

returns False if there is not enough food_name in the fridge .

This should only be used internally,after the type checking has been done"""

if type(food_name) !=type(""):

raise TypeError("input food_name type error %s" % type(food_name))

if type(quantity)!=type(1) or quantity<=0:

raise TypeError("quantity type error %s ,or int error " % type(quantity))

if (not food_name in self.items):

raise TypeError("food_name %s not in " % (food_name))

elif self.items[food_name]>quantity:

self.items[food_name] = self.items[food_name] - quantity;

elif self.items[food_name] ==quantity:

self.items[food_name] = 0

else:

return False;

def get_one(self,food_name,quantity):

"""get_one(food_name,quantity)- from the items removes the food_name ,quantity change"""

self.__get_multi(food_name,quantity)

def get_many(self, food_dict):

"""get_many(food_dict) -takes out a whole dictionary worth of food.returns a dictionary with

all of the ingredients returns False if there are not enough ingredients or if a dictionary is not provided.

"""

if type(food_dict)!=type({}):

#raise TypeError("food_dict is not a dictionary %s" % type(food_dict))

return False

for item in food_dict.keys():

if not item in self.items:

return False

elif self.items[item]<food_dict[item]:

return False

for item in food_dict.keys():

self.items[item] = self.items[item] - food_dict[item]

return self.items

self.__get_multi(food_name,quantity)

在写代码中要注意缩进的比例,不然的话将会出现异常,因为缩进比例不同的话,将会导致内部的模块遭到破坏,造成原先模块不完整。

Python中的self含义

self,1.指的是实例instance本身,是个对象object,是当前类的实例。2.使用self可以访问当前实例中对应的变量、函数。

在python中规定,函数的第一个参数就必须是实例对象本身,并且建议,约定俗成,把其名字写为self。所以需要self

29.模块操作:

也就是将函数、类放到一个py文件中,将该文件的文件名称作为该模块名称,保存后,通过import filename 应用,然后里面的类或者函数,可以用filename.classname(),或者filename.functionname()来

调用啊。第一次执行后会在源文件夹目录下产生__pycache__的文件夹,下面会有Food.cpython-33文件生成(对应python3.3.*版本)

python中如何家里包》包使用与操作系统中类似的目录(文件夹)结构,是的同一目录下的文件在一起使用时就像单独的模块。新建一个文件夹

如Kitchen,然后在该文件夹下,新建__init__.py(这个名称必须与类中该方法的名称相同,并且名称前后各有两个下划线。该文件提示Python)

这是个包目录,而不仅是包含python文件的普通目录。这可以确保开发人员知道要维护目录和控制它的行为。__init__文件包含了控制包的用法的代码,

因为与模块不同,当导入包时,目录中的每个文件并没有立即导入。相反,__init__文件首先被计算,他指定要使用的文件以及使用它们的方式。

为了将已经编写的类作为Kitchen包的一部分,在Kitchen目录下创建相应类,将相应的类放到每个文件中,并以类的名称命名文件。在windows

系统下,应该讲斜杠/看做为一个反斜杠\,分隔目录。Kitchen/Fridge.py;Kitchen/__init__.py本文件里面是空的。

在某一个文件下下创建的程序,可以通过下面方法把路径加进去:

import sys

>>> sys.path

['', 'C:\\Python33\\Lib\\idlelib', 'C:\\windows\\SYSTEM32\\python33.zip', 'C:\\Python33\\DLLs', 'C:\\Python33\\lib', 'C:\\Python33', 'C:\\Python33\\lib\\site-packages']

>>> sys.path.append("E:\Program Files\python\pythonsellfile")

>>> sys.path

['', 'C:\\Python33\\Lib\\idlelib', 'C:\\windows\\SYSTEM32\\python33.zip', 'C:\\Python33\\DLLs', 'C:\\Python33\\lib', 'C:\\Python33', 'C:\\Python33\\lib\\site-packages', 'E:\\Program Files\\python\\pythonsellfile']

>>> sys.path.append("E:\Program Files\python\pythonsellfile\Kitchen")

>>> sys.path

['', 'C:\\Python33\\Lib\\idlelib', 'C:\\windows\\SYSTEM32\\python33.zip', 'C:\\Python33\\DLLs', 'C:\\Python33\\lib', 'C:\\Python33', 'C:\\Python33\\lib\\site-packages', 'E:\\Program Files\\python\\pythonsellfile', 'E:\\Program Files\\python\\pythonsellfile\\Kitchen']

>>> import Fridge

Traceback (most recent call last):

File "<pyshell#6>", line 1, in <module>

import Fridge

File "E:\Program Files\python\pythonsellfile\Kitchen\Fridge.py", line 101

"""get_one(food_name,quantity)- from the items removes the food_name ,quantity change"""

^

IndentationError: expected an indented block

>>> import Kitchen

对于包的使用,像和模块差不错,import 包名,调用时也是包名.类名,啥的。注意路径的问题。

__init__.py中代码如下:

from Fridge import Fridge

from Omelet import Omelet

>>>import Kitchen

>>> f=Kitchen.Fridge({"apples":20,"pear":12})

>>> f.has("apples")

True

>>> f.items

{'pear': 12, 'apples': 20}

>>>

在import Kitchen 后,会在Kitchen文件夹下产生一个__pycache__文件夹,下面有__init__cpython-33 Fridge.cpython-33等文件

包是首单词大写的如Kitchen,模块就是一个复数形式如Foods.

有时候需要不用显示地指定模块中每个可用的名称而是用模块的所有内容。为此Python提供了一个特殊字符*,它用于from ...import...语句。

记住在导入全局作用域时,只能是用*进行导入,

From Foods import * ;

结果如>>> from Food import *

>>> f = Food() 可以不用Foods.Food()这样,而是可以显式调用

这时可以使用Fridge({"":2}),无须Foods.Fridge(),这样调用。

包和模块的工作方式类似,但它们内部的工作方式不同。对于包,当使用from..import.*

时,需要显示指定希望得到的名称。在__init__.py文件中使用__all__列表可使Kitchen包中的3个模块变得可用。__all__列表中出现的元素可以是

函数、类的名称或数据,它们都可以通过import*被自动导入到程序的全局作用域。为了能够处理包,必须指定一个要导出的名称列表。然而,如果模块较大,

也可以在模块文件的顶部创建__all__列表,它将在包中那样把名称限制在模块中。

>>> from Kitchen import *

>>> ome= Omelet.Omelet()

Traceback (most recent call last):

File "<pyshell#16>", line 1, in <module>

ome= Omelet.Omelet()

AttributeError: type object 'Omelet' has no attribute 'Omelet'

>>> ome = Kitchen.Omelet()

>>> ome

<Omelet.Omelet object at 0x0000000003034898>

>>> Omelet.Omelet()

Traceback (most recent call last):

File "<pyshell#19>", line 1, in <module>

Omelet.Omelet()

AttributeError: type object 'Omelet' has no attribute 'Omelet'

>>> Omelet()

在__init__.py中如此写,然后 from Kitchen import *引入全局变量中

from Fridge import Fridge

#from Omelet import Omelet

__all_ = ['Fridge','Omelet']

30.重新导入模块和包

当多个模块共享一个公共模块,并且多次在同一个程序中调用它很正常。这种情况下,python将模块的名称以及模块的来源都隐藏在一个特殊的sys.modules下

该sys.modules包含目前已经导入的全部模块。实际上代码编辑器中使用Python Shell时,它已经加载了sys以及其他许多模块。

源文件,经过编译后创建.pyc文件。可以查看sys.modules,查看到已加载的每个模块的名称。

将相应的包或者模块加入到系统模块中,然后从其中删除;

>>> import Kitchen

>>> 'kitchen' in sys.modules

False

>>> sys.modules['Kitchen']

<module 'Kitchen' from 'E:\\Program Files\\python\\pythonsellfile\\Kitchen\\__init__.py'>

>>> sys.modules['Kitchen']

<module 'Kitchen' from 'E:\\Program Files\\python\\pythonsellfile\\Kitchen\\__init__.py'>

>>> sys.modules.pop('Kitchen')

<module 'Kitchen' from 'E:\\Program Files\\python\\pythonsellfile\\Kitchen\\__init__.py'>

>>> sys.modules['Kitchen']

Traceback (most recent call last):

File "<pyshell#27>", line 1, in <module>

sys.modules['Kitchen']

KeyError: 'Kitchen'

>>>

Python中提供了一个内置的函数reload,它重新加载指定的模块,效果如上面。

import Kitchen

reload(Kitchen)

31.测试模块和包的基础知识

if __name__ == '__main__'

可以在自己的模块的尾部使用这个语句;从此刻起,可以测试类是否已经创建,函数是否返回了期望的值,或者执行其他任何您可以想要的测试。

在程序中,之前能够正常工作的代码突然崩溃是很常见的。

程序中有一个特殊名称__name__,可以告诉您正在使用的作用域的名称。例如,如果在Foods模块中检查__name__值,它返回字符串"Foods"

__main__是一个特殊的保留字,它是顶层全局作用域的名称。如果有一个从来不被直接使用的模块,可以在其尾部粘贴一些代码,这些代码只有

一个用途,即验证该模块可否正常工作。可以在自己的模块的尾部使用这个语句。

32.读写文件以及访问目录内容的函数和类型(134页)

Python提供了丰富的输入、输出函数,首先是文件对象,他是python中实现输入输出的基本方法。然后是路径操作、获取文件信息和访问目录内容的函数。

windows中路径:E:\Program Files\npp.6.0.0\notepad++用python字符串"E:\\Program Files\\npp.6.0.0\\notepad++"代替。也可以使用在开头的引号前放置字母r,

取消字符串中对反斜杠的特殊处理 r "E:\Program Files\npp.6.0.0\notepad++".因此这里我们将使用字符串对象来存储创建和访问的示例文件的路径。

windows下,输入以下代码可以使用任何路径>>>path ="C:\\sample.txt"等等。如果是LInux,>>>path ="/tmp/sample.txt"这样选择任意路径.

32.1编写文本文件:在系统上创建一个新文件,创建一个file对象,告诉python希望向文件中写数据。file对象代表对一个文件的连接,而不是文件本身,

但是如果视图打开或者向一个不存在的文件写数据,python将自动创建该文件。:

>>> def make_text_file():

a= open('text.txt',"w")

a.write("This is how you create a new text file")

a.close()

python默认的路径是安装路径,一般的上面的程序将会在安装路径下如果没有text.txt,将会创建它,并向其写入This is how you create a new text file

但是如果存在该文件的话,python将会删除它,然后新建。w参数时打算向文件中写入数据,如果没有指定该参数,python将认为是从文件中读,若文件不存在,将抛异常

def read_text_file(filename):

a=open(filename)

a

a.close()

下面是先调用系统函数判断文件是否存在,不存在在写入。

>>> import os

>>> def make_another_file():

if os.path.isfile('text.txt'):

print("you are trying to create a file that already existes!")

else:

f=open('text.txt',"w")

f.write("This is how you create a new text file!")

路径可以使相对路径,也可以是绝对路径

32.2向文件中追加文本,使用参数a,而不是用写w

>>> def add_some_text():

a=open("text.txt","a")

a.write("Here is some added data")

a.close()

>>>

>>> add_some_text()

这样是直接添加在结尾,如果想换行的话,在添加数据之前需要添加换行回车符"\r\n" \n,空格也一样,如果自己不添加空格、制表符或换行符,下一次向文件

中添加的文本会跟在已有文本之后。

This is

a new

data

even row

这个结果是使用"""个形式输入的,它按照输入的形式自动换行,因为""" """它原本就是按照原来形式输入的文本

>>> def add_some_text():

a=open("text.txt","a")

a.write("""

This is

a new

data

even row""")

a.close()

32.3读文本文件,其参数是"r"

>>> f= open("text.txt","r")

>>> data_line = f.readline()

>>> data_line

'This is how you create a new text fileHere is some added data\n'

这样的读取后面是带有回车符的,在实际处理中需要处理掉

>>> f= open("text.txt","r")

>>> data_line = f.readline()

>>> data_line

'This is how you create a new text fileHere is some added data\n'

>>> f.read()

'\nHere is some added data\n\tThis is\n\ta new\n\tdata\n\teven row'

也就是在读取过程中,我们可以看到读取的游标位置在发生变化,读操作后会自动到读取的该内容的结尾,下一次读从该处位置继续向下处理

换行符在print中是正常的,当做换行符使用。当完成读操作时,删除文件对象并关闭文件del a ;a.close()

a.readlines()可以将文件余下的内容按照行全部读取,然后可以按照循环每一行

>>> def print_line_lengths():

a=open("text.txt",'r')

text = a.readlines()

for line in text:

print(len(line))

注意特殊字符所引起的异常,可以查看具体的16进制编码来判断出来。每一行都包含换行符,看起来为空的行,其长度可能为1.

32.4文件异常

因为python程序对计算机的文件系统没有独占控制,在访问文件是它必须能够处理预料之外的错误。当python在执行文件操作并遇到问题时,

它将抛出一个IOError异常。该异常的字符串表示将描述遇到的问题。如:

试图打开并读取一个不存在的文件

试图在一个不存在的目录中创建文件

试图打开一个没有读访问权限的文件

试图在一个没有写访问权限的目录下创建文件

计算机遇到磁盘错误

32.5路径和目录因为/\的问题,可以使用os来解决

32.6os中异常

os模块中函数在失败时会抛出OSError异常。

模块os包含另外一个模块os.path,它提供了操作路径的函数。由于路径也是字符串,因此可以使用普通的字符串操作方法组合和分解文件路径。(但这样可能不易移植)

使用os.path操作,可是程序易于移植,从而可以处理一些特殊的情形。使用os.path.join可将目录名称组合成路径。如

在windows上:

>>> import os.path

>>> os.path.join("snakes",'Python')

'snakes\\Python'

linux上也会有具体对应如"snakes/Python"

os.path.split具有相反的功能,可以讲路径中的最后一个组件提取出来。该函数返回值包含两个项的元组:父目录的路劲及最后一个路径组件

>>> os.path.split("E:\Program Files\python\pythonsellfile\Kitchen")

('E:\\Program Files\\python\\pythonsellfile', 'Kitchen')

>>>

>>> file_path =os.path.split("E:\Program Files\python\pythonsellfile\Kitchen")

>>> file_path

('E:\\Program Files\\python\\pythonsellfile', 'Kitchen')

>>> file_path[0]

'E:\\Program Files\\python\\pythonsellfile'

>>> file_path_up=os.path.split(file_path[0])

>>> file_path_up

('E:\\Program Files\\python', 'pythonsellfile')

>>> os.path.join(file_path_up[0],file_path_up[0])

'E:\\Program Files\\python'

拆和和,迭代实现拆解路径

>>> def split_full(path):

parent_path,name = os.path.split(path)

if name=="":

return (parent_path, )

else:

return split_full(parent_path)+(name,)

>>> split_full("E:\Program Files\python\pythonsellfile\Kitchen")

('E:\\', 'Program Files', 'python', 'pythonsellfile', 'Kitchen')

>>>

分解路径

>>> def split_full2(path):

split_text = os.path.split(path)

if split_text[1]=="":

return (split_text[0],)

else:

return split_full2(split_text[0])+(split_text[1],)

也就是要搞清楚返回的数据格式是什么

os.path.splitext可以将文件的后缀获得

>>> os.path.splitext("mp5.gif")

('mp5', '.gif')

>>> os.path.splitext("abs.jpeg")[0]

'abs'

>>> os.path.splitext("abs.jpeg")[1]

'.jpeg'

os.path.normpath()可以规范化或清理路径

>>>print(os.path.normpath(r"C:\\Program Files\Perl\..\Python30"))

C:\Program Files\Python30

os.path.abspath函数将一个相对路径转换成绝对路径

>>> print(os.path.abspath("Program Files"))

C:\Python33\Program Files

输出取决于调用abspath时的当前路径。即使在Python目录下没有改文件或者目录,这个函数仍然可以正常工作。os.path下面的所有路径操作函数都不

检查正在操作的路径是不真正存在。

但是可以使用os.path.exists判断是否某个路径是否真实存在,相对路径是运行的路径下,绝对路径则是判读绝对路径

>>> os.path.exists("Program Files")

False

>>> os.path.exists("README.txt")

True

>>> os.path.exists("E:\Program Files\python\pythonsellfile\Kitchen")

True

>>>

返回目录下的子目录或者文件列表

>>> os.listdir("C:\\Python33")

['chapter_5_demo.py', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'LICENSE.txt', 'NEWS.txt', 'python', 'python.exe', 'pythonw.exe', 'README.txt', 'tcl', 'text.txt', 'Tools']

显示某个目录下的所有内容,但是不包含子目录下面东西

>>> def print_dir(dir_path):

for name in os.listdir(dir_path):

print(os.path.join(dir_path,name))

>>> print_dir("C:\\")

但是返回的顺序可能并不是按照什么东西排列的,因为返回的是列表,因此可以用sorted()进行排序

如果是指向文件os.path.isfile() 返回true,如果是目录os.path.isdir() True;如果路径不存在都返回False;

遍历某一个目录下所有文件,包含子文件夹下面的

>>> def print_tree(dir_path):

for name in os.listdir(dir_path):

path_full = os.path.join(dir_path,name)

if os.path.isfile(path_full):

print(path_full)

elif os.path.isdir(path_full):

print_tree(path_full)

else:

print("no file no dir %s " % path_full)

>>> print_tree("F:\\KuGou")

F:\KuGou\Cache\4455bd77c205734c4453191cc6cbc882

F:\KuGou\m2\All About That Bass.mp3

F:\KuGou\m2\Angel.mp3

F:\KuGou\m2\As Long As You Love Me.mp3

F:\KuGou\m2\Baby.mp3

F:\KuGou\m2\Because Of You.mp3

F:\KuGou\m2\Blowin In the Wind.mp3

F:\KuGou\m2\Call Me Maybe.mp3

F:\KuGou\m2\Come Get It Bae.mp3

F:\KuGou\m2\Funky.mp3

F:\KuGou\m2\不要在寂寞的时候说爱我.mp3

F:\KuGou\m2\么么哒.mp3

F:\KuGou\m2\你是我心中的一首歌.mp3

F:\KuGou\m2\侃侃 - 滴答.mp3

F:\KuGou\m2\凤凰传奇 - 最炫民族风 - k.mp3

F:\KuGou\m2\凤凰传奇 - 荷塘月色.mp

>>>

这里注意判断文件和文件夹时要用全路径,光是名字的话判断不出来

32.7 时间函数time.ctime

>>> mod_time =os.path.getmtime("C:\\Python33")

>>> print(time.ctime(mod_time))

Tue Jun 23 15:37:00 2015

>>> mod_time

1435045020.2190993

os.path.getmtime(file_path)获得该文件上次被修改的时间,只不过返回的时间是自1970年以来的相差的秒数,因此要用到time.ctime()函数进行

转换。

32.8重命名、复制,删除、移动文件

模块中shutil中包含了操作文件的函数。可以使用函数shutil.move可以重命名一个文件或者是移动到另外一个目录下

>>> import shutil

>>> shutil.move("abs.txt","text2.txt")

'text2.txt'

>>> shutil.move("text2.txt","C:\\")

Traceback (most recent call last):

File "C:\Python33\lib\shutil.py", line 522, in move

os.rename(src, real_dst)

PermissionError: [WinError 5] 拒绝访问。: 'C:\\text2.txt'

PermissionError: [Errno 13] Permission denied: 'C:\\text2.txt'

>>> shutil.move("text2.txt","E:\\")

'E:\\text2.txt'

>>> shutil.copy("E:\\text2.txt","C:\\Python33\\")

'C:\\Python33\\text2.txt'

>>> os.remove("E:\\text2.txt")

shutil.move / shutil.copy os.remove

改变一个文件或者目录的权限,可以通过os.chmod操作

轮换日志名称的例子

32.9创建和删除目录

os.mkdir(""),但是其中父路径不存在的话将会产生异常,因此可以使用os.mkdirs()创建,对于不存在的父目录也会自动创建,没有异常

os.rmdir()删除当前目录,如果要删除的目录不为空,首先要删除该目录的内容,之后再删除该目录。

shutil.rmtree("")该函数可以删除该目录(该目录下即使有内容也会被删除),慎用啊,如果,参数路径传递的不对,将会误删的。

32.10通配符,*? *.txt可以匹配所有后缀名为.txt的文件

Python在模块glob中提供了名称也为glob的函数,它实现了对目录内容进行通配的功能。glob.glob函数接受模式作为输入,并返回所有匹配的文件名和路径名列表.

在windows操作系统下,模式M*可以匹配名称以m和M开头的所有文件,因为文件名称和文件名称通配是不区分大小写的。但是在大多数其他操作系统上,通配是区分大小写的。

>>> glob.glob("F:\\KuGou\\M*")

['F:\\KuGou\\m2', 'F:\\KuGou\\m2.rar']

>>>

*匹配0个或多个任意字符,*.m*匹配扩展名以m开头的名称

?任意单个字符,???匹配恰好包含3个字符的名称

[...]方括号中列出的任意一个字符 [AEIOU]*匹配以答谢的元音字母开头的名称

[!...]不在方括号出现的任意一个字符 *[!s]匹配不以s结尾的名称

如[m-p]匹配m,n,o,p,中的任意一个字母,[!0-9]匹配数字以外任意字符

删除目录C:\\source\\中所有扩展名为.bak的备份文件,:

for path in glob.glob("C:\\source\\*.bak"):#返回的是一个列表[]

os.remove(path)

通配比os.listdir的功能强大的多,glob.glob可以返回多个目录下的路径。如返回当前目录的所有子目录中扩展名为.txt的文件

glob.glob("*\\*.txt")

(1)总结open("","")r,w,a read,write readline() readlines()

(2)文件os.path的相关操作

shutil的文件操作,os.mkdir,os.mkdirs,os.rmdir,os.rmtree

轮换日志名称的例子

import os

import shutil

def make_version_path(path,version):

if version ==0:

#No suffix for version 0,the current version.

return path

else:

#append a suffix to indicate the older version.

return path+"."+str(version)

def rotate(path,version=0):

#Construct the name of the version we're rotating.

old_path = make_version_path(path,version)

if not os.path.exists(old_path):

#It does not exist, so complain.

raise IOError("'%s' does not exist " % path)

#Construct the new version name for this file.

new_path = make_version_path(path,version+1)

#Is there already a version with this name?

if os.path.exists(new_path):

#Yes .Rotate it out of the way first !

rotate(path,version+1)

#Now we can rename the version safely.

shutil.move(old_path,new_path)

33.1一些python中特殊用法和常用模块

>>> filter_me =[1,2,3,4,6,7,8,11,12,14,15,19,22]

>>> result=filter(lambda x:x%2==0,filter_me)

>>> print(*result)

2 4 6 8 12 14 22

>>> result

<filter object at 0x0000000002FF5A20>

>>> *result

SyntaxError: can use starred expression only as assignment target

lambda是python里面的关键字,filter过滤出来满足条件的内容给result,由于缺少名称,lambda创建的函数被称为匿名函数。

可以使用lambda的结果给函数绑定一个名称,该名称只在创建名称的作用域内可用。

>>> func = lambda x: x%2==0

>>> result =filter(func,filter_me)

中间那一块也可以这么写,但是lambda中不可以使用其他语句,为变量创建一个名称也不可。在lambda内部只能执行有限的操作,比如测试相等、

两数相乘或者以特定的方式使用其他已经存在的函数。

lambda主要用在内置函数map和filter中。可以避免使用循环。

map短路循环

>>> #Now map gets to be run in the simple case

>>> map_me =['a','b','c','d','e','f','g']

>>> result = map(lambda x:"The letter is %s" % x,map_me)

>>> print(*result)

The letter is a The letter is b The letter is c The letter is d The letter is e The letter is f The letter is g

如果向map中传递一个列表(或元组),主列表中的每个序列应该有相同数目的元素。

>>> map_me_again = [[1,2,3],[4,5,6],[7,8,9]]

>>> result =map(lambda list:[list[1],list[0],list[2]],map_me_again)

>>> print(*result)

[2, 1, 3] [5, 4, 6] [8, 7, 9]

map总是返回一个迭代器。也可以传递给map一个非匿名函数的名称,运行方式相同。如下:

>>> func2 = lambda list:[list[2],list[1],list[0]]

>>> result2 = map(func2,map_me_again)

>>> print(*result2)

[3, 2, 1] [6, 5, 4] [9, 8, 7]

33.2列表解析

python2.0中引入了称为列表解析的特性。也就是在可以在列表[]中编写小的循环和判定,以此来定义用以限制被访问的元素范围的参数。

创建一个列表,并打印出列表中的偶数,可以使用列表解析:

>>> everything =[1,2,3,4,6,8,11,12,14]

>>> print([ x for x in everything if x%2==0])

[2, 4, 6, 8, 12, 14]

注意中间那一语句的格式。

列表解析,可以使用循环和条件判断;这笔lambda表达式的使用更方便。

33.3为循环生成迭代器

>>> f= range(10,20)

>>> print(*f)

10 11 12 13 14 15 16 17 18 19

>>> for number in range(10):

print("Number is now %d " % number)

Number is now 0

Number is now 1

Number is now 2

Number is now 3

Number is now 4

Number is now 5

Number is now 6

Number is now 7

Number is now 8

Number is now 9

range如果只指定一个数,那么将从0开始循环k个数,k为指定的数,但是如果k为负数的话,不会执行

>>> for num in range(-3):

print("%d" % num)

>>>

range(),可以从5,开始到55结束,步长4

range(5,55,4)

>>> range(1,10,2)

range(1, 10, 2)

>>> result = range(1,10,2)

>>> result

range(1, 10, 2)

>>> print([x for x in result])

[1, 3, 5, 7, 9]

当要循环大量的数据时,创建它,可能会导致内存不够用,进而耗尽所有的内存。python提供了一个称谓xrange的特殊内置类,只在内存中创建列表

中的少量元素。在python3.1中,range发生了变化,改为了一个迭代器。也就是像result那样,这个迭代器对象,没有公共接口而仅有私有方法,

这些私有方法看起来类似于大多数列表和元组所拥有的子集。

>>> dir(result)

['__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__reversed__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index', 'start', 'step', 'stop']

>>>

>>>result

range(10,20)

直接调用它,只是返回一个该方法的显示,但是可以通过同列表、序列、以及字典相同的[]来访问它,如

result[0]

10

33.4使用字典的特殊字符串替换

>>> person ={"name":"James","camera":"nikon","handedness":"lefty","baseball_team":"angels","instrument":"guitar"}

>>> print("%(name)s,%(camera)s,%(baseball_team)s" %person)

James,nikon,angels

使用字典方式格式化输出的内容,指定打印的内容的顺序

还有string模块(包)的使用

33.5线程的使用

34.创建模块

34.1研究模块

模块只是一个python源文件。它可以包含变量、类、函数和python脚本中可以用到的其他任何元素。

通过使用dir函数可以更好的理解模块。给dir函数传递一个python元素的名称,它将列出该元素的所有属性。如查看__builtins__属性,包括内置函数、

类和变量,可以使用以下的语句:

dir(__builtins__)

导入模块,import module ,可以对python自带的或您创建的模块使用这种语法。也可以使用如下所示的另外一种方法:

from module import item 这种方法能够仅导入所需要的一个类或函数。

如果一个模块被修改了,可以使用imp.reload函数重新加载该模块的新定义。

import module

import imp

imp.reload(module) 使用重新加载的模块替换module

使用imp.reload时,总是要使用圆括号;使用import时,不使用圆括号。

34.3查找模块

为了导入一个模块,python解释器首先找到他。对于一个模块,python解释器首先查找一个称为module.py的文件,其中module是传递给import语句

的模块的名称。当找到该模块式,python解释器将他编译成一个.pyc文件。当再次导入模块式,python解释器可以加载编译好的模块,加速python脚本的运行。

对于import语句,python解释器只查找一定数量的目录。如果python解释器不能找到您输入的名称,他将显示一个错误ImportError。

查找的目录在sys模块的sys.path变量中列出。如

>>> import sys

>>> sys.path

['', 'C:\\Python33\\Lib\\idlelib', 'E:\\Program Files\\python\\pythonsellfile,E:\\Program Files\\python\\pythonsellfile\\Kitchen', 'C:\\windows\\SYSTEM32\\python33.zip', 'C:\\Python33\\DLLs', 'C:\\Python33\\lib', 'C:\\Python33', 'C:\\Python33\\lib\\site-packages',
'E:\\Program Files\\python\\pythonsellfile\\Kitchen', 'E:\\Program Files\\python\\pythonsellfile']

34.5理解模块

因为因为python是一个开源包,可以得到python解释器和所有模块的源代码。实际。可以通过在sys.path变量列出的所有目录中查找以.py结尾的文件。

这些文件就是python模块。一些模块只包含函数,而另外一些则包含类和函数。

创建一个模块Food,并将该文件命名成Food.py

def favoriteFood():

print("print favorite food")

>>>import Food

>>>Food.favoriteFood()

但是不使用模块名的话,将会导致错误NameError,name'favoriteFood' is not defined

可以使用>>>from Food import favoriteFood

>>>favoriteFood()

34.5使用类

类保存数据和操作数据的方法。python默认可以访问类中的数据。

创建类和子类

class Meal():

"""Holds the food and drink used in a meal.

In true object-oriented tradition ,this class

includes setter methods for the food and drink .

Call printIt to pretty-print the values.

"""

def __init__(self,food='omelet',drink='coffee'):

"""Initialize to default values."""

self.name='generic meal'

self.food =food

self.drink = drink

def printIf(self,prefix=''):

"""Print the data nicely."""

print(prefix,'A FINE', self.name,' with ',self.food,' and' ,self.drink)

#Setter for the food

def setFood(self,food='omelet'):

self.food = food

#setter for the drink

def setDrink(self,drink='coffee'):

self.drink = drink

#setter for the name.

def setName(self,name=''):

self.name = name

class Breakfast(Meal):

'''Holds the food and drink for breakfast'''

def __init__(self):

'''Initialize with an omelet and coffee.'''

Meal.__init__(self,'omelet','coffee')

self.setName('breakfast')

class Lunch(Meal):

'''Holds the food and drink for lunch .'''

def __init__(self):

'''Initialize with a sandwich a lunch .''''

Meal.__init__(self,'sandwich','gin and tonic')

self.setName('midday meal')

#override setFood().

def setFood(self,food='sandwich'):

if food !='sandwich' and food !='omelet':

raise AngryChefException

Meal.setFood(self,food)

class Dinner(Meal):

'''Holds the food and drink for dinner.'''

def __init__(self):

'''Initialize with steak and merlot.'''

Meal.__init__(self)

self.setName('dinner')

def printIt(self,prefix=''):

'''print even more nicely.'''

print(prefix,'A gourment',self.name,'with',self.food,'and',self.drink)

在定义了模块的类和函数之后,下一步是完成模块,以使它更适合python用户和python解释器的约定。

完成模块的工作包括:

定义应用于模块的错误和异常

定义模块中要输出的项。定义模块的公共的API

为模块编写文档

测试模块

在模块作为程序执行的情况下提供一个回退函数。

35.6定义用于模块的异常和错误首先可以使用python定义的一些标准异常类,然后需要的话使用定义针对于特定问题的异常。

class SensitiveArtistException(Exception):

pass

class AngryChefException(SensitiveArtistException):

pass

定义异常类,但是什么也不干

35.7选择那些导出内容

使用from形似导入模块时,可以指定导入模块中的哪一项。如

from meal import AngryChefException

如果要导入所有的项,可以使用

from module import *

如:

from Meal import *

>>> import meal #meal.Meal() 模块下的

>>> from meal import * # Meal()类似全局变量

>>> f= Meal()

>>> f.printIt()

A FINE generic meal with omelet and coffee

*型号告诉python解释器导入模块的全部公有方法。python解释器使用两种方法确定哪些项应该是公有的:

如果模块中定义了变量__all__,解释器使用__all__确定哪些项是公有项。

如果模块中没有定义变量__all__,解释器导入除了名称以下划线(_)开头的项目之外的所有项,所以printIt被认为是公有的,而_printIt则不会.

最为最佳实践,应该总是在模块中定义__all__。这样可以显式控制其他python脚本的导入项。

>>> from meal import *

>>> Dinner()

Traceback (most recent call last):

File "<pyshell#1>", line 1, in <module>

Dinner()

NameError: name 'Dinner' is not defined

>>>

因为这里没有将Dinner类作为对外公开的类,所以使用会出现错误。

__all__=['Meal','AngryChefException','Breakfast','Lunch']

>>> ml = Meal()

>>> ml.printIt()

A FINE generic meal with omelet and coffee

>>>

而使用Meal则没有问题,因为在__all__中已经设置了对外公开的内容。

35.7为模块建立文档

使用"""号在模块使用文件开头,模块内部定义,类定义。函数定义等等,简洁清晰。

通过import module ;help(meal);#可以查看模块的文档。但是注意在调用help函数读入模块的文档之前,必须先导入模块。

测试

"""

Module for making meals in Python.

Import this module and then call

makeBreakfast(),makeDinner() or makeLunch().

"""

__all__=['Meal','AngryChefException','Breakfast','Lunch','Dinner','makeBreakfast','makeLunch','makeDinner']

# Helper functions.

def makeBreakfast():

'''Create a breakfast .'''

return Breakfast()

def makeLunch():

'''Create a lunch.'''

return Lunch()

def makeDinner():

'''Creates a dinner.'''

return Dinner()

# Exception classes.

class SensitiveArtistException(Exception):

'''Exception raised by an overly-sensitive artist.

Base class for artistic types.'''

pass

class AngryChefException(SensitiveArtistException):

'''Exception that indicates the chef is unhappy.'''

pass

class Meal():

"""Holds the food and drink used in a meal.

In true object-oriented tradition ,this class

includes setter methods for the food and drink .

Call printIt to pretty-print the values.

"""

def __init__(self,food='omelet',drink='coffee'):

"""Initialize to default values."""

self.name='generic meal'

self.food =food

self.drink = drink

def printIt(self,prefix=''):

"""Print the data nicely."""

print(prefix,'A FINE', self.name,' with ',self.food,' and' ,self.drink)

#Setter for the food

def setFood(self,food='omelet'):

self.food = food

#setter for the drink

def setDrink(self,drink='coffee'):

self.drink = drink

#setter for the name.

def setName(self,name=''):

self.name = name

class Breakfast(Meal):

'''Holds the food and drink for breakfast'''

def __init__(self):

'''Initialize with an omelet and coffee.'''

Meal.__init__(self,'omelet','coffee')

self.setName('breakfast')

class Lunch(Meal):

'''Holds the food and drink for lunch .'''

def __init__(self):

'''Initialize with a sandwich a lunch .'''

Meal.__init__(self,'sandwich','gin and tonic')

self.setName('midday meal')

#override setFood().

def setFood(self,food='sandwich'):

if food !='sandwich' and food !='omelet':

raise AngryChefException

Meal.setFood(self,food)

class Dinner(Meal):

'''Holds the food and drink for dinner.'''

def __init__(self):

'''Initialize with steak and merlot.'''

Meal.__init__(self)

self.setName('dinner')

def printIt(self,prefix=''):

'''print even more nicely.'''

print(prefix,'A gourment',self.name,'with',self.food,'and',self.drink)

def test():

'''Test function.'''

print('module meal test...')

#Generic no arguments.

print("Testing Meal class .")

m= Meal()

m.printIt("\t")

m = Meal('green eggs and ham','tea')

m.printIt("\t")

#Test breakfast

print('Testing Breakfast class ...')

b= Breakfast()

b.printIt("\t")

b.setName('breaking of the fast')

b.printIt("\t")

#Test dinner

print("testing Dinner class.")

d = Dinner()

d.printIt("\t")

#test lunch

print("testing Lunch class.")

l=Lunch()

l.printIt("\t")

print('calling lunch.setFood().')

try:

l.setFood('hotdog')

except AngryChefException:

print("\t",'The chef is angry.Picl an omelet.')

#Run test if this modul is run as a program

if __name__=='__main__':

test()

注意模块名称不用和相关变量名等重复,不然会造成覆盖的错误。

35.8安装模块

python解释器在sys.path变量中列出的目录中查找模块。sys.path变量包括当前目录,所以总是可以使用当前路径中的模块。然而,如果希望在多个

脚本或者多个系统使用我们编写的模块,需要将他们安装到sys.path变量列出的某个目录下。

大多数情况下,需要将python模块放到site-packages目录中查看sys.path列出的目录,找到一个亿site-packages结尾的目录名。

除了创建模块,还可以创建模块的包,包是一个安装到相同目录结构的相关模块的集合。可以参考相关内容

三种机制安装模块:

(1)手动创建一个安装脚本或程序

(2)创建一个针对于我们操作系统的安装程序,如windows上MSI文件,Linux上的RPM文件,mac上的DMG文件

(3)使用方便的python distutils(分发实用程序)包,来创建基于python的安装文件。

第(3)种方法,需要创建一个名为setup.py的安装脚本,最简单的安装脚本如下:

from distutils.core import setup

setup(name='NameOfModule',

version='1.0',

py_modules=['NameOfModule'],)

需要两次包括模块的名称。用我们新建的模块替代NameOfModule。创建脚本后可以使用下面命令创建一个模块的发布版本

python setup.py sdist

参数sdist时software distribution(软件分发)的缩写。可以通过cmd到python安装目录下,执行该句。会在python安装命令下

有个dist文件夹下生成meal-1.0.zip的文件(模块的压缩文件)。

将该文件放到其他系统上,并安装模块。首先解压缩,并对其进行扩展。linux、unix、mac os x下,使用目命令:

$gunzip meal-1.0.tar.gz

$tar vxf meal-1.0.tar

windows 上可以python setup.py install

会在python安装目录下产出一个build文件夹,其中有lib文件夹,下面是meal.py

使用distutils的好处是它能用于几乎任何的python模块。安装命令相同。另一个好处是安装程序会创建模块的文档,可用

pydoc命令查看,这是一个模块。也可以

import meal

help(meal)

>>> import meal

>>> help(meal)

Help on module meal:

NAME

meal

DESCRIPTION

Module for making meals in Python.

Import this module and then call

makeBreakfast(),makeDinner() or makeLunch().

CLASSES

builtins.object

Meal

Breakfast

Dinner

Lunch

SensitiveArtistException(builtins.Exception)

AngryChefException

class AngryChefException(SensitiveArtistException)

| Exception that indicates the chef is unhappy.

|

| Method resolution order:

| AngryChefException

| SensitiveArtistException

| builtins.Exception

| builtins.BaseException

| builtins.object

|

| Data descriptors inherited from SensitiveArtistException:

|

| __weakref__

| list of weak references to the object (if defined)

|

| ----------------------------------------------------------------------

| Methods inherited from builtins.Exception:

|

| __init__(...)

| x.__init__(...) initializes x; see help(type(x)) for signature

|

| ----------------------------------------------------------------------

| Data and other attributes inherited from builtins.Exception:

|

| __new__ = <built-in method __new__ of type object>

| T.__new__(S, ...) -> a new object with type S, a subtype of T

|

| ----------------------------------------------------------------------

| Methods inherited from builtins.BaseException:

|

| __delattr__(...)

| x.__delattr__('name') <==> del x.name

|

| __getattribute__(...)

| x.__getattribute__('name') <==> x.name

|

| __reduce__(...)

|

| __repr__(...)

| x.__repr__() <==> repr(x)

|

| __setattr__(...)

| x.__setattr__('name', value) <==> x.name = value

|

| __setstate__(...)

|

| __str__(...)

| x.__str__() <==> str(x)

|

| with_traceback(...)

| Exception.with_traceback(tb) --

| set self.__traceback__ to tb and return self.

|

| ----------------------------------------------------------------------

| Data descriptors inherited from builtins.BaseException:

|

| __cause__

| exception cause

|

| __context__

| exception context

|

| __dict__

|

| __suppress_context__

|

| __traceback__

|

| args

class Breakfast(Meal)

| Holds the food and drink for breakfast

|

| Method resolution order:

| Breakfast

| Meal

| builtins.object

|

| Methods defined here:

|

| __init__(self)

| Initialize with an omelet and coffee.

|

| ----------------------------------------------------------------------

| Methods inherited from Meal:

|

| printIt(self, prefix='')

| Print the data nicely.

|

| setDrink(self, drink='coffee')

| #setter for the drink

|

| setFood(self, food='omelet')

| #Setter for the food

|

| setName(self, name='')

| #setter for the name.

|

| ----------------------------------------------------------------------

| Data descriptors inherited from Meal:

|

| __dict__

| dictionary for instance variables (if defined)

|

| __weakref__

| list of weak references to the object (if defined)

class Dinner(Meal)

| Holds the food and drink for dinner.

|

| Method resolution order:

| Dinner

| Meal

| builtins.object

|

| Methods defined here:

|

| __init__(self)

| Initialize with steak and merlot.

|

| printIt(self, prefix='')

| print even more nicely.

|

| ----------------------------------------------------------------------

| Methods inherited from Meal:

|

| setDrink(self, drink='coffee')

| #setter for the drink

|

| setFood(self, food='omelet')

| #Setter for the food

|

| setName(self, name='')

| #setter for the name.

|

| ----------------------------------------------------------------------

| Data descriptors inherited from Meal:

|

| __dict__

| dictionary for instance variables (if defined)

|

| __weakref__

| list of weak references to the object (if defined)

class Lunch(Meal)

| Holds the food and drink for lunch .

|

| Method resolution order:

| Lunch

| Meal

| builtins.object

|

| Methods defined here:

|

| __init__(self)

| Initialize with a sandwich a lunch .

|

| setFood(self, food='sandwich')

| #override setFood().

|

| ----------------------------------------------------------------------

| Methods inherited from Meal:

|

| printIt(self, prefix='')

| Print the data nicely.

|

| setDrink(self, drink='coffee')

| #setter for the drink

|

| setName(self, name='')

| #setter for the name.

|

| ----------------------------------------------------------------------

| Data descriptors inherited from Meal:

|

| __dict__

| dictionary for instance variables (if defined)

|

| __weakref__

| list of weak references to the object (if defined)

class Meal(builtins.object)

| Holds the food and drink used in a meal.

| In true object-oriented tradition ,this class

| includes setter methods for the food and drink .

|

| Call printIt to pretty-print the values.

|

| Methods defined here:

|

| __init__(self, food='omelet', drink='coffee')

| Initialize to default values.

|

| printIt(self, prefix='')

| Print the data nicely.

|

| setDrink(self, drink='coffee')

| #setter for the drink

|

| setFood(self, food='omelet')

| #Setter for the food

|

| setName(self, name='')

| #setter for the name.

|

| ----------------------------------------------------------------------

| Data descriptors defined here:

|

| __dict__

| dictionary for instance variables (if defined)

|

| __weakref__

| list of weak references to the object (if defined)

FUNCTIONS

makeBreakfast()

Create a breakfast .

makeDinner()

Creates a dinner.

makeLunch()

Create a lunch.

DATA

__all__ = ['Meal', 'AngryChefException', 'Breakfast', 'Lunch', 'Dinner...

FILE

c:\python33\meal.py

这样来查看。

36.文本处理

36.1文本处理

脚本语言非常适用于:对目录树中的各种文件进行简单搜索和处理。目录导航、正则表达式。文件的导航可以使用第八章的分隔和合并目录。

可以用作桌面文件搜索、日志剪辑。邮件筛选

os.getcwd(),返回当前目录

os.listdir(directory)返回一个存储在指定的directory目录中的文件名和子目录列表

os.stat(path) 返回一个数值元组,该元组给出任何您可能需要的关于文件或目录的信息。

(st_mode文件的访问权限 ,st_ino节点数unix,st_dev设备号,st_uid所有者的用户id,st_gid所有者的组id,st_size文件大小,st_atime最后访问时间

st_mtime最后修改时间,st_ctime创建时间,这几个时间是从1970年到现在的描述)

需要用time.ctime

import time

>>> result=os.stat("text2.txt")

>>> result

nt.stat_result(st_mode=33206, st_ino=3659174697414283, st_dev=0, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1435053002, st_mtime=1435053002, st_ctime=1435053002)

>>> result[-1]

1435053002

>>> import time

>>> print(time.ctime(result[-1]))

Tue Jun 23 17:50:02 2015

>>>

可以使用result[i],i为下标

os.path.split(path)将路径分隔为符合当前操作系统的组成名称。返回一个元组,不是一个列表

os.path.join(components)将名称连接成为一个符合当前操作系统的路径

os.path.normcase(path)规范路径的大小写。

os.walk(top,topdown=True,onerror=None,followlinks=False)它自上而下或自底而上迭代目录树。对于每个目录,它

创建一个由dirpath,dirnames和filenames组成的三元组。dirpath部分是一个保存目录路径的字符创。dirnames部分是dirpath中

子目录的列表,不包括“.”,".."。最后,dirnames是dirpath中每个非目录文件的一个列表。

1)列出文件并处理路径:

1

>>> import os,os.path #导入模块

>>> os.getcwd() #获得当前路径

'C:\\Python33'

>>> os.path.split(os.getcwd()) #分切

('C:\\', 'Python33')

>>> os.stat('.') #显示当前目录的状态信息

nt.stat_result(st_mode=16895, st_ino=7599824371210189, st_dev=0, st_nlink=1, st_uid=0, st_gid=0, st_size=4096, st_atime=1435226656, st_mtime=1435226656, st_ctime=1434511988)

>>>

#列出当前目录下的文件和文件夹

>>> os.listdir(".")

['build', 'ch10_class_subclass.py', 'chapter_5_demo.py', 'dist', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'LICENSE.txt', 'MANIFEST', 'meal.py', 'NEWS.txt', 'python.exe', 'pythonw.exe', 'README.txt', 'setup.py', 'tcl', 'text.txt', 'text2.txt', 'Tools', '__pycache__']

>>>

寻找当前目录下的pdf文件

import os,os.path

import re

def print_pdf(root,dirs,files):

for file in files:

path = os.path.join(root,file)

#norm the upper or lower alpha

path = os.path.normcase(path)

if re.search(r".*\.pdf",path):

print(path)

for root ,dirs,files in os.walk("."):

print_pdf(root,dirs,files)

if __name__=="__main__":

print("i am here")

形式r"<string constant>"简单的告诉python,字符串常量应该禁止对反斜杠作出任何特殊处理。r"\n"是一个两个字母长度的字符串,

表示一个反斜杠字符后面跟着一个字母"n"。因此可以通过r开关控制正则表达式的反斜杠。

>>> import re #re 为正则表达式模块

>>> s=('xxx','abcxxxabc','xyx','abc','x.x','axa','axxxxa','axxya')

>>> a= filter((lambda s:re.match(r'xxx',s)),s) #匹配xxx

>>> print(a)

<filter object at 0x0000000002E8ECF8>

>>> print(*a)

xxx

>>> b=filter((lambda s:re.search("xxx",s)),s) #搜索含有xxx

>>> print(*b)

xxx abcxxxabc axxxxa

>>> c=filter((lambda s:re.search(r'x.x',s)),s) #搜索x.x ,中间的点可以看做为占位符

>>> print(*c)

xxx abcxxxabc xyx x.x axxxxa

>>> d=filter((lambda s:re.search(r'x\.x',s),s))
#搜索x.x

Traceback (most recent call last):

File "<pyshell#9>", line 1, in <module>

d=filter((lambda s:re.search(r'x\.x',s),s))

TypeError: filter expected 2 arguments, got 1

>>> d=filter((lambda s:re.search(r'x\.x',s)),s)

>>> print(*d)

x.x

>>>

>>> e=filter((lambda s:re.search(r'x.*x',s)),s)

>>> print(*e)

xxx abcxxxabc xyx x.x axxxxa axxya

*号可以匹配它前面的一串任意字符,会匹配两个x之间出现的0个或更多个字符。

如果两个x之间什么都没有,

>>> f=filter((lambda s:re.search(r"x.+x",s)),s)

>>> print(*f)

xxx abcxxxabc xyx x.x axxxxa

+号匹配一个或更多个字符。

>>> g=filter((lambda s:re.search(r'c+',s)),s)

>>> print(*g)

abcxxxabc abc 匹配只有一个字母c的.

匹配其中没有一个c的任何字符串,必须在字符串的开始和结束使用^ $,然后告诉re的是从头到尾不包含c字符的字符串:

>>> i=filter((lambda s:re.search(r'^[^c]*$',s)),s)

>>> print(*i)

xxx xyx x.x axa axxxxa axxya 匹配不包含c的字符串

在当前目录下匹配pdf文件

>>> s=('dudu.hu','1.pdf','2.pde','abc.pdf')

>>> f=filter((lambda s:re.search(r'.*\.pdf',s)),s)

>>> f

<filter object at 0x0000000002E7BFD0>

>>> print(*f)

1.pdf abc.pdf

.匹配任意字符(有时除'\n'外),*匹配0个或者多个前面的字符,\为转义字符\.为.,然后是pdf,也就是匹配任意名称的pdf文件

>>> g=filter((lambda s:re.search(r'.\.hu',s)),s)

>>> print(*g)

dudu.hu

匹配s中含有.hu的内容

os.walk('.')返回一个三元组的循环,形式如下

('.\\Lib\\multiprocessing\\__pycache__', [], ['process.cpython-33.pyc', 'util.cpython-33.pyc', '__init__.cpython-33.pyc'])

('.\\Lib\\pydoc_data', ['__pycache__'], ['topics.py', '_pydoc.css', '__init__.py']) ('.\\Lib\\pydoc_data\\__pycache__', [], [])

('.\\Lib\\site-packages', ['__pycache__'], ['meal-1.0-py3.3.egg-info', 'meal.py', 'mypath.pth', 'README.txt'])

('.\\Lib\\site-packages\\__pycache__', [], ['meal.cpython-33.pyc'])

import os,os.path

import re

def print_pdf(arg,dir,files):

for file in files:

path = os.path.join(dir,file)

path =os.path.normcase(path)

if not re.search(r'.*\.pdf',path):

continue

if not re.search(r'.\.hu',path):

continue

print(path)

for root ,dirs,files in os.walk('.'):

print_pdf(root,root,files)

if __name__=='__main__':

print('scan2_pdf.py is running')

在当前文件夹下寻找***.hu/*.pdf的文件。或者其子文件的下面有相关的pdf文件等等。

re.search(r'(du){2}\.pdf',path):是选择du出现两次,()中的整体

[du]+只要出现一次或者多次

[du]{1},{m}只出现m次,[]其中的字符可能出现了m次,这里是[]中可能的字符.(du){m}匹配m个du

if not re.search(r'.*(du){2}.*\.pdf',path)如果想要匹配一串是,最好使用(){}这种形式,同时需要注意是开头匹配,中间匹配,还是结尾匹配

.* 匹配一段文本中任意字符

if re.search(r'.*(du).*',path):# [du]+ 包含du

continue

这一块需要摇摇学习。

37.测试

37.1断言

断言就是假设是正确的,但是如果一旦错误,以前的论点可能就不会成立了。如果一个称为__debug__的特殊内部变量为True,就检查断言。如果任何一个断言没有

成功,就会引发一个AssertionError错误。因为断言实际上是一个if语句与raise的组合,当出现问题时,就会raise一个异常。

>>> large =1000

>>> string='This is a string'

>>> float =1.0

>>> brokean_int ="this should have been an int"

>>> assert large>500

>>> assert type(string)==type("")

>>> assert type(float)!=type(1)

>>> assert type(broken_int)==type(4)

Traceback (most recent call last):

File "<pyshell#7>", line 1, in <module>

assert type(broken_int)==type(4)

NameError: name 'broken_int' is not defined

>>>

可以使用

try:

assert type(broken_int) ==type(4),"broken_int is broken"

excep AssertionError:print("Handle the error here.")

激活断言的变量__debug__是一个特殊的变量,在python启动之后它便不可修改,为了将其关闭,可以使用-O参数告诉python对代码进行优化,

意味着除了执行其他的优化处理外,还将删除断言测试。

断言本身具有几个缺点。首先,断言不提供用于运行测试的结构。只能了解了需要从测试中的到什么,测试才能帮助确认代码是否正确。

断言只是停止程序并提供一个异常。能够提供一些总结的系统将会更有用处,以便对测试进行命名、增加测试、删除测试以及将若干测试编译为一个程序包,

使得我们能够针对这个程序进行了充分的测试进行总结。这些想法以及一些更多的想法构成了单元测试盒测试套件的概念。

37.2测试用例和测试套件

单元测试以测试用例为主要内容,而测试用例是所测试情况的可测试代码块的最小结构单元。当使用PyUnit时,测试用例是一个简单对象,

其中至少包括一个运行代码的测试方法;当测试完成时,它接着将测试的结果与您所作出的有关结果的各种断言进行比较。

PyUnit是其开发者为这个程序包起的名称,但是导入的模块具有一个听起来更加通用的名称unittest.

每个测试用例都是TestCase类的子类,TestCase是一个恰当而易于记忆的名称。只要重写TestCase类的runTest方法,就可以定义一个基本的测试,

这是可以写出的最简单的测试用例,但是也可以在单个测试用例类中定义若干个不同的测试方法,这样就可以定义许多测试公有的部分,例如:安装和清除过程。

测试套件是同时运行于一个特定项目的一系列测试用例。可以找到一些用于组织测试套件的简单工具。

import unittest

class ArithTest(unittest.TestCase):

def runTest(self):

"""Test addition and succeed."""

self.failUnless(1+1==2, 'one plus one fails!')

self.failIf(1+1 != 2, 'one plus one fails again!')

self.failUnlessEqual(1+1,2,'more trouble with one plus one!')

def suite():

suite = unittest.TestSuite()

suite.addTest(ArithTest())

return suite

if __name__=='__main__':

runner = unittest.TextTestRunner()

test_suite = suite()

runner.run(test_suite)

导入unittest(包含PyUnit框架的模块)之后,定义ArithTest类,它是unittest中的类TestCase的子类.ArithTest只定义了runTest方法,该方法执行

实际的测试工作。注意runTest方法中定义了文档字符串。对测试进行文档注释至少与对代码进行文档注释是一样重要的。最后在runTest方法中使用了3

个断言。

在定义了ArithTest之后,创建了suite函数,简单的实例化一个寻常的、未修改的测试套件。它将一个单元测试加入其中并返回它。为了创建一个能返回的

对象,suite函数调用了TestCase类。实际的测试是由返回的TestCase对象执行。

只有在作为主程序运行时,python才会调用TextTestRunner类去创建runner对象。runner对象有一个run方法,接受unittests.TestSuite类的一个对象作为

参数。suite函数创建这样的一个对象,因此test_suite被赋值为TestSuite对象的一个引用。当完成上述操作时,runner.run方法被调用,它使用test_suite

中的suite函数,以完成在test_suite中定义的单元测试。

import unittest

class ArithTest(unittest.TestCase):

def runTest(self):

"""Test addition and succeed."""

self.failUnless(1+1==2, 'one plus one fails!')

self.failIf(1+1 != 2, 'one plus one fails again!')

self.failUnlessEqual(1+1,2,'more trouble with one plus one!')

class ArithTestTwo(unittest.TestCase):

def runTest(self):

self.failIfEqual(1+1,2,'expected failure here')

self.failIfEqual(1+1,2,'expected failure')

def suite():

suite = unittest.TestSuite()

suite.addTest(ArithTest())

suite.addTest(ArithTestTwo())

return suite

if __name__=='__main__':

runner = unittest.TextTestRunner()

test_suite = suite()

runner.run(test_suite)

第一个测试正确为.,第二个测试为F

.F

>>> ================================ RESTART ================================

>>>

.F

======================================================================

FAIL: runTest (__main__.ArithTestTwo)

----------------------------------------------------------------------

Traceback (most recent call last):

File "E:/Program Files/python/pythonsellfile/ch12_test1.py", line 11, in runTest

self.failIfEqual(1+1,2,'expected failure here')

AssertionError: 2 == 2 : expected failure here

----------------------------------------------------------------------

Ran 2 tests in 0.013s

FAILED (failures=1)

一切都很好,而且进行的很顺利,但是实际的测试通常还包括在运行测试之前准备测试(创建文件、创建合适的目录结构、保证一切都处于良好的状态,以及为保证对

正确的对象进行测试所需要做的其他工作。)另外在测试结束时经常需要做一些清理工作。

在PyUnit中,测试用例所运行的环境被称为测试装置test fixture。基本的TestCase类定义了两个方法:setUp在运行测试前调用,tearDown在测试用例完成后调用。

这两个方法用于处理测试装置的创建和清理中所涉及的工作。如果setUp失败,tearDown将不被调用。然而,即使测试用例本身失败,tearDown也仍将被调用。

记住当创建测试时,每个测试的初始状态不应该依赖于之前测试成功还是失败。每个测试用例应该为自己创建一个原始的测试装置。如果不能保证这一点,那么将会得到

不一致的测试结果。

为了节省时间,当在一个相同配置的测试装置上,重复运行一些相似的测试时,可以创建TestCase类的子类来定义设置方法和清除方法。这将得到一个可以作为

起点使用的单个类。一旦完成了上述工作,建立该类的子类以定义每个测试用例。也可以选择在单元测试用例类中定义若干个测试用例方法,然后为每个方法实例化测试用例对象。

import unittest

class ArithTestSuper(unittest.TestCase):

def setUp(self):

print("Setting up ArithTest casses")

def tearDown(self):

print("Cleaning up ArithTest cases")

class ArithTest(ArithTestSuper):

def runTest(self):

"""Test addition and succeed."""

print("Running ArithTest")

self.failUnless(1+1==2,'one plus one fails')

self.failIf(1+1!=2,'one plus one fails again!')

self.failUnlessEqual(1+1,2,'more trouble with one plus one!')

class ArithTestFail(ArithTestSuper):

def runTest(self):

"""Test addition and fail."""

print("Running ArithTestFail")

self.failUnless(1+1==2,'one plus one fails!')

self.failIf(1+1!=2,'one plus one fails again!')

self.failUnlessEqual(1+1,2,'more trouble with one plus one')

self.failIfEqual(1+1,2,"expected failure here")

self.failIfEqual(1+1,2,'second failure')

class ArithTest2(unittest.TestCase):

def setUp(self):

print('setting up ArithTest2 cases')

def tearDown(self):

print('cleaning up arithtest2 cases')

def runArithTest(self):

"""test addition and succeed ,in one class."""

print("running ArithTest in ArithTest2")

self.failUnless(1+1==2,'one plus one fails')

self.failIf(1+1!=2,'one plus one fails again')

self.failUnlessEqual(1+1,2,'more trouble with one plus one')

def runArithTestFail(self):

"""test addition and fail ,in one class."""

print("running ArithTestFail in ArithTest2")

self.failUnless(1+1==2,'one plus one fails')

self.failIf(1+1!=2,'one plus one fails again')

self.failUnlessEqual(1+1,2,'more trouble with one plus one')

self.failIfEqual(1+1,2,'expected failure here')

self.failIfEqual(1+1,2,'second failure')

def suite():

suite = unittest.TestSuite()

#First style:

suite.addTest(ArithTest())

suite.addTest(ArithTestFail())

#second style:

suite.addTest(ArithTest2("runArithTest"))

suite.addTest(ArithTest2("runArithTestFail"))

return suite

if __name__=='__main__':

runner = unittest.TextTestRunner()

test_suite = suite()

runner.run(test_suite)

>>> ================================ RESTART ================================

>>>

Setting up ArithTest cases

Running ArithTest

Cleaning up ArithTest cases

.Setting up ArithTest cases

Running ArithTestFail

Cleaning up ArithTest cases

Fsetting up ArithTest2 cases

running ArithTest in ArithTest2

cleaning up arithtest2 cases

.setting up ArithTest2 cases

running ArithTestFail in ArithTest2

cleaning up arithtest2 cases

F

======================================================================

FAIL: runTest (__main__.ArithTestFail)

Test addition and fail.

----------------------------------------------------------------------

Traceback (most recent call last):

File "E:/Program Files/python/pythonsellfile/ch12_test2.py", line 23, in runTest

self.failIfEqual(1+1,2,"expected failure here")

AssertionError: 2 == 2 : expected failure here

======================================================================

FAIL: runArithTestFail (__main__.ArithTest2)

test addition and fail ,in one class.

----------------------------------------------------------------------

Traceback (most recent call last):

File "E:/Program Files/python/pythonsellfile/ch12_test2.py", line 44, in runArithTestFail

self.failIfEqual(1+1,2,'expected failure here')

AssertionError: 2 == 2 : expected failure here

----------------------------------------------------------------------

Ran 4 tests in 0.092s

FAILED (failures=2)

>>>

注意第一点所做的测试与之前的测试相同。一个测试成功,另一个测试失败,但是所做的是两组测试,每组测试都利用同一个测试装置,

但却以不同的方式实现多个单元测试用例。

代码中的第一组类(ArithTestSuper、ArithTest和ArithTestFail)与test1.py中的第二组示例本质相同,但是这个创建一个名为ArithTestSuper的类。

ArithTestSuper实现setUp和tearDown 方法。这两个方法没有完成太多功能,但是他们确实显示了将要引入语句的位置。每个单元测试类是新的ArithTestSuper类的

子类,因此现在它们将对测试装置进行相同的设置。如果需要更改测试装置,那么现在可以在ArithTestSuper的类中进行更改,而且此更改在其所有的子类中生效。

ArithTest2定义了两个测试用例方法:runArithTest和runArithTestFail。在测试运行期间,创建测试用例实例是,这两个方法被显示的调用,从suite被更改的

定义中可以看到这点。

极限编程整合,在一个不断扩展的编码项目的开发过程中使用一个测试套件。这种策略是极限编程方法的基础。极限编程是编程的一种流行趋势:

首先,对编码进行计划;然后将测试用例集合编写为一种框架;之后才编写实际的代码。在完成编码任务后的任何时候,可以重新运行该测试套件以查看接近

设计目标的程度,该测试套件具体体现了这个设计目标(当然,同时也在调试测试套样),这种技术是一种在软件过程早期发现编程错误的非常好的方法,可以定位低层次代码

中的故障,在进一个开展高层次工作之前使代码稳定下来,而且在python中使用PyUnit建立这个过程是及其容易的。

创建一个包含几个文件的测试目录,然后再测试用例完成之后清理该测试目录。所有测试用例方法的命名约定,,即使用test加上方法名,例如testMyFunction,这样使

unittest.main过程能够对他们进行自动地识别和运行。

这种编程方法的第一步与其他的方法一样是定义目标,在此示例中,就是可以在工作使用的一种通用的可重用的搜索功能。

完成此类任务的一个很好的想法是首先关注核心功能,在最初的代码已经处于良好的状态之后再增加更多的一些功能。这种软件开发的增量式方法可以帮助我们防止

在进行一些根本性的工作之前就陷入到细节中,而且类似这种通用使用程序的软件的功能非常复杂,很容易失去思路。

import unittest

import find

import os,os.path

def filename(ret):

return ret[1]

class FindTest(unittest.TestCase):

def setUp(self):

os.mkdir("_test")

os.mkdir(os.path.join("_test","subdir"))

f = open(os.path.join("_test","file1.txt"),"w")

f.write("""first line

second line

third line

fourth line""")

f.close()

f = open(os.path.join("_test","file2.py"),"w")

f.write("""This is a test file.

It has many words in it.

This is the final line.""")

f.close()

def tearDown(self):

os.unlink(os.path.join("_test","file1.txt"))

os.unlink(os.path.join("_test","file2.py"))

os.rmdir(os.path.join("_test","subdir"))

os.rmdir("_test")

def test_01_SearchAll(self):

"""1: Test Searching for all files. """

res = find.find(r".*",start="_test")

self.failUnless(map(filename,res)==['file1.txt','file2.py'],'wrong results')

def test_02_SearchFileName(self):

"""2: Test searching for specific file by regexp."""

res = find.find(r"file",start="_test")

self.failUnless(map(filename,res)==['file1.txt','file2.py'],'wrong results')

res = find.find(r"py$",start='_test')

self.failUnless(map(filename,res)==['file2.py'],'python file search incorrect')

def test_03_SearchByContent(self):

"""3; Test searching by content."""

res =find.find(start="_test",content="first")

self.failUnless(map(filename,res)==['file1.txt'],"didn't find file1.txt")

res = find.find(where="py$",start="_test",content="line")

self.failUnless(map(filename,res)==['file2.py'],"didn't find file2.py")

res = find.find(where="py$",start="_test",content="second")

self.failUnless(len(res)==0,"found something that didn't exist")

def test_04_SearchByExtension(self):

"""4: Test searching by file extension."""

res = find.find(start="_test",ext='py')

self.failUnless(map(filename,res)==['file2.py',"didn't find file2.py"])

res = find.find(start="_test",ext="txt")

self.failUnless(map(filename,res)==['file1.txt'],"didn't find file1.txt")

def test_05_SearchByLogic(self):

"""5: Test searching using a logical combination callback."""

res = find.find(start="_test",logic=lambda x:(x['size']<50))

self.failUnless(map(filename,res)==['file1.txt'],'failed to find by size')

if __name__=='__main__':

unittest.main()

>>>

import unittest

import find

import os,os.path

测试套件开始引入unittest测试模块,和将要测试的内容find,并且还有要使用到的模块。接着

def filename(ret):

return ret[1]

定义了一个简单的帮助函数,用于从搜索结果中提取出文件名,使对结果的正确性的检查变得更加简单。

然后往下是测试套件本身。所有的测试用例都是基类FindTest的实例。FindTest类首先用setUp和tearDown方法定义了测试用例中使用的测试装置,

接着定义了5个测试用例。

所有测试用例中的测试装置都包含一个测试目录;此目录下的一个子目录,用于保证在扫描时子目录不会被作为文件处理;以及两个以.txt和.py为扩展

名的测试文件。

测试用例本身用一个序数和一个描述性名称命名,并且每个测试用例以字符串test开头。因此在运行测试套件时,unittest.main函数可以自动发现它们。

因为在测试时使用一个简单的字符排序对测试进行排序,所以该序数保证测试将按照定义的适当的次序进行。

如果脚本是直接运行的,那么将使用该测试用例中的unittest.main创建一个默认的测试运行程序。然后unittest.main调用找到所有的测试用例,按照序数

对它们进行排序,并按次序运行这些测试用例。

第二个文件是find实用程序本身的框架。定义它的功能是什么,并且说明如何对它进行调用。

import os,os.path

import re

from stat import *

def find(where='.*',content=None,start='.',ext=None,logic=None):

#return ([])

context= {}

context['where'] = where

context['content'] = content

context['return'] = []

os.walk(start,find_file,context)

return context['return']

def find_file(context,dir,files):

for file in files:

#find out things about this file.

path = os.path.join(dir,file)

path = os.path.normcase(path)

try:

ext = os.path.splitext(file)[1][1:]

except:

ext = ''

stat = os.stat(path)

size = stat[ST_SIZE]

#Don't treat directories like files

if S_ISDIR(stat[ST_MODE]):continue

#Do filtration based on the original parameters of find()

if not re.search(context['where'],file):continue

#Do content filtration last ,to avoid it as much as possible

if context['content']:

f= open(path,'r')

match = 0

for l in f.readlines():

if re.search(context['content'],l):

match = 1

break

f.close()

if not match:continue

#Build the return value for any files that passed the filtration tests.

file_return = (path,file,ext,size)

context['return'].append(file_return)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: