python 第二周

九、字典

1.基础介绍

①Python将单词称为键(key),将单词对应的含义称为值(value)

②字典是python唯一的映射类型,字符串、元组和列表都是序列类型

列表中的索引值和对应元素的值没有关系,两个列表中唯一的关系是索引值相同的元素有对应关系

③用{}表示字典,由多个健和其对应的值组成,索引时用[ ];健和值的组合称为项

④也可用dict这个工厂函数(类型,不是一般的BIF)创建一个字典

2.基本用法

2.1空字典:dict={}

2.2键入方式:

2.2.1

 dict = (1:’one ‘,2:’two’,3:’three’)

             索引:dict[2]

                   ‘two’

2.2.2元组的方式

括号的个数,因为dict()只接受一个参数,所以用()把键值对包括起来成为元组

python 第二周

2.2.3关键字参数

dict4 =dict(小甲鱼=‘让编程改变世界’)           #小甲鱼不能加引号

索引:dict4

      小甲鱼=‘让编程改变世界’                 

2.2.4 直接改变字典的值

①若改变字典中原有健的值:

dict4[‘小甲鱼‘] = ‘让python改变世界’

索引:dict4

      {‘小甲鱼’: ‘让python改变世界’}

②字典中没有的健

dict4[‘爱迪生’]=’天才是…’

索引:ditc4

       {‘小甲鱼’: ‘让python改变世界’, ‘爱迪生’:’天才是…’}

3.内置方法

3.1 adict.keys() 返回一个包含字典所有KEY的列表;

3.2 adict.values() 返回一个包含字典所有value的列表;

3.3 adict.items() 返回一个包含所有(键,值)元祖的列表;

python 第二周

3.4 adict.clear() 删除字典中的所有项或元素;

3.5 adict.copy() 返回一个字典浅拷贝的副本;

python 第二周

直接赋值并没有创建新的内存空间

3.6 adict.fromkeys(seq, val=None) 创建并返回一个新字典,以seq中的元素做该字典的键,val做该字典中所有键对应的初始值(默认为None);

fromkeys(…)  创建并返回一个新的字典

dict. fromkeys(s[,v]) -> New dict with keys from S and

values equal to v (v defaults to None)

 

python 第二周

初始化一个空字典:

python 第二周

注意,仅仅是返回一个新字典,并不能改变旧字典,要想改变必须用a = a.fromkeys

3.7 adict.get(key, default = None)

返回字典中key对应的值,若key不存在字典中,则返回default的值(default默认为None);

python 第二周

一般来说如果试图访问字典中不存在的项时会出错,而用get就不会

3.8 in 、 not in;

3.9 adict.iteritems()、adict.iterkeys()、adict.itervalues() 与它们对应的非迭代方法一样,不同的是它们返回一个迭代子,而不是一个列表;

3.10 adict.pop(key[,default]) 和get方法相似。如果字典中存在key,删除并返回key对应的vuale;如果key不存在,且没有给出default的值,则引发keyerror异常;

python 第二周

3.11 adict.setdefault(key, default=None) 和set()方法相似,但如果字典中不存在Key键,由 adict[key] = default 为它赋值;

python 第二周

3.12 adict.update(bdict) 将字典bdict的键值对添加到字典adict中。

字典中的键,值,键值对用  .keys()  .values()  .items()表示 

python 第二周

 

 

十、集合

无序 去重 不能索引

num = {}

type(num) –>’dict’

num2 ={1,2,3,4,5}

type(num2) –> ‘set’

num2 = {1,1,1,1,1,2,2,2,,2,,2}

–> {1,2}

1.创建的两种方法

用{} 把数字 括起来.

set() : set1 = set([1,1,1,1,2,2,2,2,2,2])

2.如何访问set中的值

for 打印

in 方法 1 in num1

3.num2.add(9) 添加

4.num2.remove(9) 删除

frozen 冻结的,设置一个不可变set

num3 = frozeset([1,2,3,666])

这种set不能添加

28-文件-想输出.

1.打开文件

使用 open 打开文件.

help()

十一、文件

1.用open打开文件:

打开的模式有:

‘r’-以只读方式打开文件(默认)

‘w’-以写入的方式打开 文件,会覆盖已存在的文件

‘x’-如果文件已经存在,使用此模式打开将引发异常

‘a’-0双写入模式撕开,如果文件存在,则在末尾追加写入

‘b’-以二进制模式打开文件

‘t’-以文本模式打开(默认)

‘+’-可读写模式(可添加到其他模式中使用)

‘U’-通用换行符支持.

例:

open(‘e:\test.txt’) # 两个\因为要转译(可以用u”),打开方式用了默认所以就不用写

f = open(‘e:\test.txt’) # 赋值给一个对象

2.文件对象的方法:

f.close() 关闭文件

f.read(size = -1) 从文件读取size个字符,当未给定size或给定负值的时候,

读取剩余的所有字符,然后作为字符串返回.指针移动到文件的不可末尾.

f.readline() 以写入模式打开,如果文件存在,则在末尾追加写入

f.write(str) 将字符串str写入文件

f.writelines(seq) 向文件写入字符串序列seq,seq应该是一个返回字符串的可迭代对象.

f.seek(offset,from) 在文件中移动文件指针,从from(0代表文件起始位置,1代表当前位置,2代表文件末尾)偏移offset个字节

f.tell() 返回当前在文件中的位置.

可以用list(f)把文件直接转换成为一个列表.

python 第二周

3.读取文件对象中的内容:

for i in f: (推荐这种方法)

print(i)

4.文件的写入:

打开方式一定要是 ‘a’或’w’

f = open(‘e:\test.txt’,’w’)

f.write(‘xxoo’)

f.close

5.

例1:

def save_file(goy, girl, count):

file_name_boy = ‘boy_’ + str(count) + ‘.txt’

filr_name_girl = ‘girl’ + str(count) + ‘.txt’

boy_file = open(file_name_body, ‘w’)

girl_file = open(file_name_girl, ‘w’)

boy_file.writelines(boy)

boy_file.writelines(girl)

boy_file.close()

girl_file.close()

def split_file(file_name):

f= open(‘test.txt’)

boy = []

girl = []

count = 1 # 计算

for each_line in f:

if each_line[:6] != ‘====’: # 前6个字符是等号

这里我们进行字符串分割

(role, line_spoken) = each_line.split(‘:’, 1)

if role == ‘小甲鱼’:

boy.append(line_spoken)

if role == ‘小客服’:

girl.append(line_spoken)

else:

 

6.文件的保存

save_file(boy, girl, count)

boy = []

boy = []

count += 1

save_file(boy, girl, count)

f.close()

split_file(‘recode.txt’)

 

 

十二、os模块和os.path模块

Python os

模块包含普遍的操作系统功能,注意括号中需要使用字符串

1.getcwd()

返回当前工作目录

2.chdir(path)

改变工作目录

3.listdir(path='.')

列举指定目录中的文件名('.'表示当前目录,'..'表示上一级目录)

4.mkdir(path)

创建单层目录,如该目录已存在抛出异常

5.makedirs(path)

递归创建多层目录,如该目录已存在抛出异常,注意:'E:\\a\\b'和'E:\\a\\c'并不会冲突

6.remove(path)

删除文件

7.rmdir(path)

删除单层目录,如该目录非空则抛出异常

8.removedirs(path)

递归删除目录,从子目录到父目录逐层尝试删除,遇到目录非空则抛出异常

9.rename(old, new)

将文件old重命名为new

10.system(command)

运行系统的shell命令

 

以下函数没有参数

11.os.curdir

指代当前目录('.')

12.os.pardir

指代上一级目录('..')

13.os.sep

输出操作系统特定的路径分隔符(Win下为'\\',Linux下为'/')

14.os.linesep

当前平台使用的行终止符(Win下为'\r\n',Linux下为'\n')

15.os.name

指代当前使用的操作系统(包括:'posix', 'nt', 'mac', 'os2', 'ce', 'java')

 

os.path模块

1.basename(path)

去掉目录路径,单独返回文件名

2.dirname(path)

去掉文件名,单独返回目录路径

3.join(path1[, path2[, ...]])

将path1, path2各部分组合成一个路径名

4,split(path)

分割文件名与路径,返回(f_path, f_name)元组。如果完全使用目录,它也会将最后一个目录作为文件名分离,且不会判断文件或者目录是否存在

5.splitext(path)

分离文件名与扩展名,返回(f_name, f_extension)元组

6.getsize(file)

返回指定文件的尺寸,单位是字节

7.getatime(file)

返回指定文件最近的访问时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算)

8.getctime(file)

返回指定文件的创建时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算)

9.getmtime(file)

返回指定文件最新的修改时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算)

 

以下为函数返回 True 或 False

10.exists(path)

判断指定路径(目录或文件)是否存在

11.isabs(path)

判断指定路径是否为绝对路径

12.isdir(path)

判断指定路径是否存在且是一个目录

13.isfile(path)

判断指定路径是否存在且是一个文件

14.islink(path)

判断指定路径是否存在且是一个符号链接

15.ismount(path)

判断指定路径是否存在且是一个挂载点

16.samefile(path1, paht2)

判断path1和path2两个路径是否指向同一个文件

 

十三、pickle模块

以二进制保存数据

三步走:打开文件,用pickle.dump()方法将数据放入文件,关闭文件

1 import pickle

2 my_list = [1,2,'老王',['abc']]

3 pickle_file = open('my_list.pkl','wb') #文件名后缀无所谓

4 pickle.dump(my_list,pickle_file)

5 pickle_file.close()

 

这样文件夹中就保存了my_list.pkl文件,(查询当前目录是用 import os   os.getcwd())

读取数据

打开文件,调用pickle.load()方法

pickle_file = open('my_list.pkl','rb')

list2 = pickle.load(pickle_file)

print(list2)

 

十四、异常

常见异常类型:

AttributeError:属性错误,特性引用和赋值失败时会引发属性错误
NameError:试图访问的变量名不存在
SyntaxError:语法错误,代码形式错误
Exception:所有异常的基类,因为所有python异常类都是基类Exception的其中一员,异常都是从基类Exception继承的,并且都在exceptions模块中定义。
IOError:一般常见于打开不存在文件时会引发IOError错误,也可以解理为输出输入错误
KeyError:使用了映射中不存在的关键字(键)时引发的关键字错误
IndexError:索引错误,使用的索引不存在,常索引超出序列范围,什么是索引
TypeError:类型错误,内建操作或是函数应于在了错误类型的对象时会引发类型错误
ZeroDivisonError:除数为0,在用除法操作时,第二个参数为0时引发了该错误
ValueError:值错误,传给对象的参数类型不正确,像是给int()函数传入了字符串数据类型的参数。

 

捕获异常

try语句一旦被检测出异常,剩下的语句将不会被执行

几种搭配:

1.try except

1 try:

2     sum = 1/0

3 except ZeroDivisionError:

4     print('出错')

 

可以指明出错原因:

1 try:

2     sum = 1/0

3 except ZeroDivisionError as reason:

4     print('出错,错误原因:',str(reason))

 

可以用多个except语句:

 

1 try:

2     f = open("nofile.txt")

3     sum = 1/0

4 except IOError as reason:

5     print('出错,错误原因:',str(reason))

6 except ZeroDivisionError as reason:

7     print('出错,错误原因:',str(reason))

 

可以用一个元组捕获多个异常:

1 try:

2     sum = 1/0

3     f = open("nofile.txt")

4 except (IOError,ZeroDivisionError) as reason:

5     print('出错,错误原因:',str(reason))

 

用while True 和 else 组合,else后的语句在没有异常的情况下才执行,注意缩进,输入错误后会重新输入直到正确:

 

 1 while True:

 2     try:

 3         x = int(input("input first num"))

 4         y = int(input("input first num"))

 5         z = x/y

 6         print(z)

 7     except ZeroDivisionError:

 8         print("error,try again")

 9     else:

10         break

 

不管try语句中是否发生异常,finally语句后都会执行:

 

1 try:

2     x = int(input("input first num"))

3     y = int(input("input first num"))

4     z = x/y

5     print(z)

6 except ZeroDivisionError:

7     print("error:")

8 finally:

9     print("结束")

 

 

十五、else语句及简洁的whith语句

else:

if-else语句:

和各种语言相同的用法,在条件语句中,与if语句搭配使用的else语句。如果if语句的条件表达式的结果布尔值为假,那么程序将执行else语句后的代码。

elif(else-if)语句:

elif是python提供的else-if语句,它检查多个条件表达式的值是否为真,并在为真时执行特定代码块中的代码。和else一样,elif是可选的,但是要注意的是,一个if语句可以跟多个elif语句,但最后只能有一个else语句

while-else/for-else语句:

在其他语言中,除了条件语句,是不会见到else分支的,但在Python中,while和for循环中,也是可以使用else语句的。它们的工作顺序为:在循环中使用时,else语句只在循环完成后执行,也就是说,break语句也会跳过else代码块,只要循环是正常结束,而不是通过break,else语句就会执行

求素数:

 

 1 def fun(num):

 2     count = int(num/2)

 3     while count>1:

 4         if(num%count == 0):

 5             print("%d的最大公约数是:%d" %(num,count))

 6             break

 7         count -= 1

 8     else:

 9         print("%d是素数" %num)

10

11 n = int(input("请输入一个整数:"))

12 fun(n)

 

 

执行结果:

python 第二周

注意:Python中没有自增自减运算符,格式化输出多个字符要用元组的形式

try-else语句:

对于python中的错误和异常,try-except语句段,也可以和else连用,其功能和循环中的else语句没有多大区别:在try范围内没有检测到异常的时候,执行else子句。

 

with:

这个语法是用来代替传统的try...finally语法的。

with EXPRESSION [ as VARIABLE] WITH-BLOCK

1 try:

2     with open("e://1.txt",'r') as f:

3         for each_line in f:

4             print(each_line)

5 except IOError as reason:

6     print("Error:",str(reason))

 如果用finally,若是文件不存在,也要走f.close(),这样的话文件存在打开后会自动关闭

十六、图形用户界面入门

1.动动手

0.先练练手,把我们的刚开始的那个猜数字小游戏加上界面吧?

import easygui as g

import random

 

g.msgbox('嗨,欢迎进入第一个界面小游戏!')

secret = random.randint(1,10)

 

msg = "猜猜我心中的数字是什么(0~10):"

title = "数字小游戏"

guess = g.integerbox(msg, title, lowerbound = 0, upperbound = 10)

 

while True:

    if guess == secret:

        g.msgbox('你是我肚里的蛔虫吗!')

        break

    else:

        if guess > secret:

           g.msgbox('猜大了呀,再试试')

        else:

           g.msgbox('猜小了呀,再试试')

        guess = g.integerbox(msg, title, lowerbound = 0, upperbound = 10)

 

g.msgbox('游戏结束,不玩啦!')

1.实现一个用于登记用户账号信息的界面(如果是带*号的必填项,要求一定要有输入并且不能是空格)。

from easygui import *

msg = "输入你的个人信息"

title = "登录界面"

fieldNames = ["账号名*","密码*","地址","联系电话*","邮箱地址"]

fieldValues = []  # 创建一个空列表存放账号信息

fieldValues = multenterbox(msg,title, fieldNames)

 

# 确保带*号的信息不为空

while 1:

    if fieldValues == None:

       break

    errmsg = ""

    for i in range(len(fieldNames)):

      if (fieldValues[i].strip() == "") and (fieldNames[i][-1] == "*"):

        errmsg = errmsg + ('"%s" 是必填项.\n\n' % fieldNames[i])

    if errmsg == "":

       break

    fieldValues = multenterbox(errmsg, title, fieldNames, fieldValues)

print("个人信息:", fieldValues)

2.提供一个文件浏览框,让用户选择需要打开的文本文件,打开并显示文件内容。

import easygui as g 

import os 

     

file_path = g.fileopenbox(default = "*.txt") 

     

with open(file_path) as f: 

    title = os.path.basename(file_path) 

    msg = "文件【%s】的内容如下:" %title 

    text = f.read() 

    g.textbox(msg, title, text) 

3.在上一题的基础上增强功能:当用户点击“OK”按钮的时候,比较当前文件是否修改过,如果修改过,则提示“覆盖保存”、“放弃保存”或“另存为…”并实现相应的功能。

import easygui as g 

import os 

 

file_path = g.fileopenbox(default = "*.txt") 

 

with open(file_path) as old_file: 

    title = os.path.basename(file_path) 

    msg = "文件【%s】的内容如下:" %title 

    text = old_file.read() 

    text_after = g.textbox(msg, title, text)

 

if text != text_after[:-1]:

    #textbox的返回值会追加一个换行符

    choice = g.buttonbox("文件已修改,请做出选择:", "警告", ("覆盖保存", "放弃保存", "另存为…"))

    if choice == "覆盖保存":

       with open(file_path, "w") as old_file:

           old_file.write(text_after[:-1])

    if choice == "放弃保存":

       pass

    if choice == "另存为…":

       another_path = g.filesavebox(default = ".txt")

       if os.path.splitext(another_path)[1] != '.txt':

           another_path += '.txt'

       with open(another_path, "w") as new_file:

           new_file.write(text_after[:-1])

4.写一个程序统计你当前代码量的总和,并显示离十万行代码量还有多远?

 要求一:递归搜索各个文件夹

要求二:显示各个类型的源文件和源代码数量

要求三:显示总行数与百分比

import easygui as g

import os

 

 

def show_result(start_dir):

    lines = 0

    total = 0

    text = ""

 

    for i in source_list:

       lines = source_list[i]

       total += lines

       text += "【%s】源文件 %d 个,源代码 %d 行\n" % (i, file_list[i], lines)

    title = '统计结果'

    msg1 = '您目前共写了 %d 行代码,完成进度:%.2f %%\n离10万行代码还差 %d 行,请继续努力!' % (total, total/1000, 100000 - total)

    msg2 = '您目前共写了 %d 行代码,完成进度:%.2f %%\n超额完成 %d 行,真棒!' % (total,  total/1000, total - 100000)

    if total <= 100000:

       g.textbox(msg1, title, text)

    else:

       g.textbox(msg2, title, text)

 

def calc_code(file_name):

    lines = 0

    with open(file_name) as f:

       print('正在分析文件:%s ...' % file_name)

       try:

           for each_line in f:

              lines += 1

       except UnicodeDecodeError:

           pass

    return lines

 

def search_file(start_dir):

    os.chdir(start_dir)

 

    for each_file in os.listdir(os.curdir):

       ext = os.path.splitext(each_file)[1]

       if ext in target:

           lines = calc_code(each_file)

           try:

              file_list[ext] += 1

           except KeyError:

              file_list[ext] = 1

 

           try:

              source_list[ext] += lines

           except KeyError:

              source_list[ext] = lines

       if os.path.isdir(each_file):

           search_file(each_file)

           os.chdir(os.pardir)

 

target = ['.c', '.cpp', '.py', '.cc', '.java','.pas', '.asm']

file_list = {}

source_list = {}

 

g.msgbox("请打开您存放所有代码的文件夹......", "统计代码量")

path = g.diropenbox("请选择你的代码库:")

 

search_file(path)

show_result(path)

 

 

十七、类和对象

类:

–封装(数据,函数)

–对象也是封闭,模拟真实世界

–从表态分类,从动作分类.,也就是属性和方法.属性+方法=对象

–属性可以理解为变量,方法可能理解为函数.

–类,实例对象. 类就是为了量产对象.

–类命名大写字母开头

OO的特征:OO = Object Oriented 面向对象

1.封闭 ,信息隐蔽技术.

2.继承,继承别的类的方法和属性

3.多态,不同对象对同一方法响应的行动.

对象:

1.self是什么?

–定义的时候必须写在函数的第一个参数

例:

class Ball:

def setName(self, name):

self.name = name

def kick(self):

print(‘我叫s%,谁踢我…’% self.name)

a = Ball

a.setName(‘1’)

b = Ball

b.setName(‘2’)

c = Ball

c.setName(‘3’)

–>a.kick()

–>b.kick()

–>c.kick()

2.魔法方法

init(self) 构造方法

例:

class Ball:

def init(self, name)

self.name =name

def kick(self):

print(‘我叫s%,谁踢我…’% self.name)

b = Ball(‘222’)

b.kick()

3.公有和私有

–对象的属性和方法都是公有的

例:

class Person:

name = ‘xx’

p = Person()

p.name

私有:

在Python中定义私有变量只需要在变量名或函数名前加上’__’两个下划线,

那么这个函数或变量就会为私有的了.

class Person:

__name = ‘xx’

p = Person()

p.name # 就调用不出来了.须要加上下面的语句

def getName(self):

return self.__name

p.getName() # 这样就可以调用

其实Python把__name改为了p._person__name来存储,所以找不到了.

4.继承:

–对于相似的类,就可以继承

语法: class 类名(父类名):

例:

class Parent(object):

def hello(self):

print(‘正在调用父类方法’)

class Child(Parent):

p = Person

p.hello()

c = Child()

c.hello()

如果子类中定义与父类同名的方法或属性,则会自动覆盖浆糊对应的方法或属性.

class Child(Parent):

def hello(self):

print(‘正在调用子类的方法…’)

这样就会覆盖掉子类的方法.

例:

import random as r

class Fish:

def init(self):

self.x = r.randint(0, 10)

self.y = r.randint(0, 10)

def move(self):

self.x -= 1

print(‘我的位置是:’,self.x, self.y)

class Goldfish(Fish):

pass

class Carp(Fish):

pass

class Salmon(Fish):

pass

class Shark(Fish):

def init(self):

self.hungry = True

def eat(self):

if self.hungry:

print(‘吃吃吃吃吃~~’)

else:

print(‘我特么不饿~~~’)

开始调用:

fish = Fish()

fish.move()

fish.move()

goldfish = Goldfish()

goldfish.move()

goldfish.move()

shark = Shark()

shark.eat()

shark.eat()

shark.move() # 这样会出错,因为子类的 def__int__(self)覆盖了父类的def__init__方法所以没有坐标了.

所以就要腹用如下方法:

-调用未绑定的父类方法

在__init__下加入:

Fish.__init__(self) # 这就是未绑定的父类方法.这里的self代表shark

-使用super函数

只要写 super().__init__() 就可以了. 这种更方便好用.

好处是不用给出父类的名字

!!#!#!#!#!!这里没听懂!!!!

多重继承:

class Base1:

def foo1(self):

print(‘1’)

class Base2:

def foo2(self):

print(‘2’)

class Base3(Base1, Base2)

pass

c = Base3()

c.foo1

c.foo2

上面就是多重继承,但是如果不是已经明确的了解就不要使用.

多重继承容易导致不可预见的BUG,对于程序来讲不可预的BUG几乎就是致命的

类的组合

类之间没用明显继承关系可以用组合,比如一个电话簿的类由电话和地址类组合起来:

python 第二周

 1 class Tel:

 2     def __init__(self,x):

 3         self.info = x

 4

 5 class Add:

 6     def __init__(self,y):

 7         self.info = y

 8

 9 class Notebook:

10     def __init__(self,x,y):

11         self.tel = Tel(x)

12         self.add = Add(y)

13     def print_info(self):

14         print("Tel:%s\nAdd:%s" %(self.tel.info,self.add.info))

python 第二周

python 第二周

 

类 类对象 实例对象

python 第二周

python 第二周

类对象就像C++中的static变量,一个对象有了实例对象后就将类对象的值覆盖了

属性名如果和方法名相同,属性会覆盖方法 

 

绑定

对象.__dict__返回对象拥有的属性

python 第二周

对象调用后方法绑定到实例对象上del类后,a的方法还是存在的,因为A的方法和属性都是static,程序退出前不会消失

python 第二周

 

一些和类相关的BIF

issubclass(class, classinfo)

python 第二周
isinstance(object, classinfo)

python 第二周
hasattr(object, name)  注意第二个参数要用字符串格式

python 第二周
getattr(object, name[, default])

python 第二周
setattr(object, name, value)  设置属性

delattr(object, name)     删除属性,属性不存在抛出异常 

python 第二周

property()

为什么用property

首先一个实例化的对象可以进行直接的赋值和修改,如c.age = 10,但是这样没法做参数检查,我就可以让c.age = 1000,这显然是不合理的

于是,用方法可以对参数进行检查,可以用c.setage(66)来设置年龄,但是这样就不方便了

函数property的基本功能就是把类中的方法当作属性来访问,为什么用方法来操作

python 第二周

 1 class C:

 2     def __init__(self,age = 10):

 3         self.age = age

 4     def getage(self):

 5         return self.age

 6     def setage(self,value):

 7         if 0 <= value <= 120:

 8             self.age = value

 9         else:

10             print("年龄非法")

11     def delage(self):

12         del self.age

13     x = property(getage,setage,delage)

python 第二周