python笔记(五)

1. 异常 exception
异常汇总
AssertionError 断言语句(assert)失败<eg1>
AttributeError 尝试访问未知的对象属性<eg2>
EOFError 用户输入文件末尾标志EOF(Ctrl+d) 
FloatingPointError 浮点计算错误 
GeneratorExit generator.close()方法被调用的时候 
ImportError 导入模块失败的时候 
IndexError 索引超出序列的范围<eg3>
KeyError 字典中查找一个不存在的关键字<eg4>
KeyboardInterrupt 用户输入中断键(Ctrl+c) 
MemoryError 内存溢出(可通过删除对象释放内存) 
NameError 尝试访问一个不存在的变量 
NotImplementedError 尚未实现的方法 
OSError 操作系统产生的异常(例如打开一个不存在的文件) 
OverflowError 数值运算超出最大限制 
ReferenceError 弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象 
RuntimeError 一般的运行时错误 
StopIteration 迭代器没有更多的值 
SyntaxError Python的语法错误 
IndentationError 缩进错误 
TabError Tab和空格混合使用 
SystemError Python编译器系统错误 
SystemExit Python编译器进程被关闭 
TypeError 不同类型间的无效操作 
UnboundLocalError 访问一个未初始化的本地变量(NameError的子类) 
UnicodeError Unicode相关的错误(ValueError的子类) 
UnicodeEncodeError Unicode编码时的错误(UnicodeError的子类) 
UnicodeDecodeError Unicode解码时的错误(UnicodeError的子类) 
UnicodeTranslateError Unicode转换时的错误(UnicodeError的子类) 
ValueError 传入无效的参数 
ZeroDivisionError 除数为零

部分举例:
>>> my_list = ['我是帅哥', '你是美女']
>>> assert len(my_list) > 0
>>> my_list.pop()
'你是美女'
>>> my_list.pop()
'我是帅哥'
>>> assert len(my_list) > 0
Traceback (most recent call last):
  File "<pyshell#856>", line 1, in <module>
    assert len(my_list) > 0
AssertionError #断言语句(assert)失败
>>> my_list.abcd
Traceback (most recent call last):
  File "<pyshell#857>", line 1, in <module>
    my_list.abcd
AttributeError: 'list' object has no attribute 'abcd'#尝试访问未知的对象属性
>>> my_list = [1, 2, 3]
>>> my_list[3]
Traceback (most recent call last):
  File "<pyshell#859>", line 1, in <module>
    my_list[3]
IndexError: list index out of range #索引超出序列的范围
>>> my_list[2]
3
>>> my_dict = {'one':1, 'two':2, 'three':3}
>>> my_dict['one']
1
>>> my_dict['four']
Traceback (most recent call last):
  File "<pyshell#863>", line 1, in <module>
    my_dict['four']
KeyError: 'four' #字典中查找一个不存在的关键字
>>> my_dict.get('four')
>>> #dict.get(...)方法比较安全合适

2. 异常检测与处理
(1) try语句一旦检测出现异常,则剩下的其他代码则不会执行;
(2) raise Exception_name 主动引发一个自定义异常名字的异常,可定义异常描述;

 

try:
#检测范围
except Exception[as reason]:
#出现异常(Exception)后的处理代码
finally:
#无论如何都会被执行的代码(收尾工作)

举例:
try:
    f = open('我为什么是一个文件.txt')
    print(f.read())
    f.close()
except OSError:
    print('文件出错啦T_T')
运行:
文件出错啦T_T

举例:

try:
    f = open('我为什么是一个文件.txt')
    print(f.read())
    f.close()
except OSError as reason:
    print('文件出错啦T_T\n错误的原因是:' + str(reason))
运行:
文件出错啦T_T
错误的原因是:[Errno 2] No such file or directory: '我为什么是一个文件.txt'

举例:

try:
    sum = 1 + '1'
    f = open('我为什么是一个文件.txt')
    print(f.read())
    f.close()
except (OSError, TypeError):  #多个异常同时捕获
    print('出错啦T_T')
运行:出错啦T_T

try:
    f = open('我为什么是一个文件.txt', 'w')
    print(f.write('我存在了!'))  #没有finally时并不会写入文件
    sum = 1 + '1'
    f.close()
except (OSError, TypeError):
    print('出错啦T_T')
finally:
    f.close()
运行:
5
出错啦T_T

>>> raise ZeroDivisionError('除数为0的异常')
Traceback (most recent call last):
  File "<pyshell#872>", line 1, in <module>
    raise ZeroDivisionError('除数为0的异常')
ZeroDivisionError: 除数为0的异常

3. 丰富的esle-简洁的with

else

举例:while-else / for-else
def showMaxFactor(num):
    count = num // 2
    while count > 1:
        if num % count == 0:
            print('%d最大的约数是%d' % (num, count))
            break
        count -= 1
    else: #while循环完没有break就会执行else
        print('%d是素数!' % num)

num = int(input('请输入一个数:'))
showMaxFactor(num)

举例:try-else
try:
    print(int('123'))
except ValueError as reason:
    print('出错啦:' + str(reason))
else:
    print('Good!没有任何异常。')
运行:
123
Good!没有任何异常。

with as

举例:
try:
    with open('data.txt', 'w') as f: #比 f = open(...) 多了文件不使用时自动关闭功能
    for each_line in f:
        print(each_line)
except OSError as reason:
    print('出错啦:' + str(reason))
#finally:   #有了with就不需要finally去调用关闭,会自动关闭
#f.close()  #如果文件data.txt不存在就试图去关闭一个不存在的文件

4. 图形用户界面 EasyGui

EasyGui官网:http://easygui.sourceforge.net

安装方法:
(1) 使用命令窗口cmd切换到easygui所在文件的目录下
(2) 【Windows下】执行C:\Python35\python.exe setup.py install
> "C:\Program Files (x86)\python\python.exe" setup.py install
#生成了文件模块库C:\Program Files (x86)\python\Lib\site-packages\easygui.py
> "C:\Program Files (x86)\python\python.exe" easygui.py
#easygui的演示程序

windows中系统路径
C:\Users\Jan> "C:\Program Files (x86)\python\python.exe"
>>> import sys
>>> sys.path
['', 
'C:\\Program Files (x86)\\python\\python35.zip', 
'C:\\Program Files (x86)\\python\\DLLs', 
'C:\\Program Files (x86)\\python\\lib', 
'C:\\Program Files (x86)\\python', 
'C:\\Program Files (x86)\\python\\lib\\site-packages']

IDLE中系统路径:
>>> import easygui as g
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    import easygui as g
ImportError: No module named 'easygui'
>>> import sys
>>> sys.path
['', 
'C:\\Users\\Jan\\AppData\\Local\\Programs\\Python\\Python35\\Lib\\idlelib', 
'C:\\Users\\Jan\\AppData\\Local\\Programs\\Python\\Python35\\python35.zip', 
'C:\\Users\\Jan\\AppData\\Local\\Programs\\Python\\Python35\\DLLs', 
'C:\\Users\\Jan\\AppData\\Local\\Programs\\Python\\Python35\\lib', 
'C:\\Users\\Jan\\AppData\\Local\\Programs\\Python\\Python35', 
'C:\\Users\\Jan\\AppData\\Local\\Programs\\Python\\Python35\\lib\\site-packages']
>>> sys.path.append('C:\\Program Files (x86)\\python\\python35.zip')
>>> sys.path.append('C:\\Program Files (x86)\\python\\DLLs')
>>> sys.path.append('C:\\Program Files (x86)\\python\\lib')
>>> sys.path.append('C:\\Program Files (x86)\\python')
>>> sys.path.append('C:\\Program Files (x86)\\python\\lib\\site-packages')
>>> import easygui as g  #import ... as ... 导入模块的同时重定义模块名字
>>> g.msgbox('嗨,python!')
'OK'
>>> 
# No error, success... 但每次重启IDLE都需要将windows下的sys.path进行添加。

# 示例,gui界面文字小游戏
import easygui as g
import sys
while 1:
        g.msgbox("嗨,欢迎进入第一个界面小游戏^_^")
        msg ="请问你希望在鱼C工作室学习到什么知识呢?"
        title = "小游戏互动"
        choices = ["谈恋爱", "编程", "OOXX", "琴棋书画"]
        choice = g.choicebox(msg, title, choices)
        # note that we convert choice to string, in case
        # the user cancelled the choice, and we got None.
        g.msgbox("你的选择是: " + str(choice), "结果")
        msg = "你希望重新开始小游戏吗?"
        title = "请选择"
        if g.ccbox(msg, title):    # show a Continue/Cancel dialog
                pass  # user chose Continue
        else:
                sys.exit(0)     # user chose Cancel

5.类和对象 class and object

面向对象(Object Oriented)
(1) python约定类名以大写字母开头
(2) 面向对象特征:封装(信息隐蔽)、继承(子类共享父类公共内容)、多态(不同对象对同一方法响应不同的行动)

类的示例
class Turtle:
#属性
color = 'green'
weight = 60
legs = 2
shell = True
age = 26
#方法
def climb(self):
print('我正在学习...')
def run(self):
print('我正在奔跑...')

运行:
>>> tt = Turtle()  #类Turtle的示例对象tt
>>> Turtle
<class '__main__.Turtle'>
>>> type(Turtle)
<class 'type'>
>>> type('abc')
<class 'str'>
>>> tt.climb()
我正在学习...
>>> tt.run()
我正在奔跑...

#封装
>>> list1 = [2, 1, 7, 5, 3]
>>> list1.sort()  #sort() 方法封装在list1对象中
>>> list1
[1, 2, 3, 5, 7]
>>> list1.append(9)  #append() 方法封装在list1对象中
>>> list1
[1, 2, 3, 5, 7, 9]

#继承
>>> class Mylist(list):
pass
>>> list2 = Mylist()
>>> list2.append(5)  #list2可以使用append()方法,继承了Mylist(list)中的list参数类
>>> list2.append(3)
>>> list2.append(7)
>>> list2
[5, 3, 7]
>>> list2.sort()
>>> list2
[3, 5, 7]

#多态
>>> class A:
def fun(self):
print('我是小A')
>>> class B:
def fun(self):
print('我是小B')
>>> a = A()
>>> b = B()
>>> a.fun()  #不同对象对同一方法响应不同的行动
我是小A
>>> b.fun()  #不同对象对同一方法响应不同的行动
我是小B

6.self
相当于C++的this指针(指向当前对象本身的地址),表明类自身
举例:
>>> class Ball:
def setName(self, name):  #默认self的写法
self.name = name
def kick(self):  #默认self的写法
print('我叫%s, 该死的谁踢我...' % self.name)
>>> a = Ball()
>>> a.setName('球A')
>>> b = Ball()
>>> b.setName('球B')
>>> c = Ball()
>>> c.setName('土豆')
>>> a.kick()
我叫球A, 该死的谁踢我...
>>> c.kick()
我叫土豆, 该死的谁踢我...

7.魔法方法:__init__(self)
__init__(self, parma1, parma2, ...)
举例:
>>> class Ball:
def __init__(self, name):
self.name = name
def kick(self):
print('我叫%s,该死的,谁踢我!!' % self.name)
>>> b = Ball('土豆')
>>> b.kick()
我叫土豆,该死的,谁踢我!!
>>> a = Ball()  #__init__默认设置了name,所以必须传递name实参,否则报错
TypeError: __init__() missing 1 required positional argument: 'name'

8.公有和私有
name mangling 名字改变/名字重造

公有成员:默认创建的成员均为公有。
私有成员:
(1) 在变量或函数名前加上"_"两个下划线即可。
(2) python中类的私有均属于伪私有,通过"对象._类_变量"的形式可以访问私有成员
举例:
>>> class Person:
__name = 'yuan.jiang'
>>> p = Person()
>>> p.name
AttributeError: 'Person' object has no attribute 'name'
>>> p.__name
AttributeError: 'Person' object has no attribute '__name'
>>> class Person:
__name = 'yuan.jiang'
def getName(self):
return self.__name
>>> p = Person()
>>> p.getName()
'yuan.jiang'
>>> p._Person__name  #python中类的私有属于伪私有,此方式可访问私有成员
'yuan.jiang'

9.继承 inherit

class DerivedClassName(BaseClassName):

...

(1) 如果子类中定义于父类同名的成员时,则会自动覆盖父类对应的方法或属性

(2) 解决子类中__init()

举例
>>> class Parent:
def hello(self):
print('正在调用父类的方法...')
>>> class Child(Parent):
pass
>>> p = Parent()
>>> p.hello()
正在调用父类的方法...
>>> c = Child()
>>> c.hello()
正在调用父类的方法...
>>> class Child(Parent):
def hello(self):
print('正在调用子类的方法...')
>>> c = Child()
>>> c.hello()
正在调用子类的方法...
>>> p.hello()
正在调用父类的方法...

举例
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 Carpfish(Fish):
    pass
class Salmonfish(Fish):
    pass
class Sharkfish(Fish):
    def__init__(self):  #重写了__init__方法覆盖了父类的__init__子类无法调用到self.x和self.y属性成员,导致了子类无法访问到父类的属性或方法的问题
        self.hungry = True
    def eat(self):
        if self.hungry:
            print('吃货的梦想就是天天有的吃^_^')
            self.hungry = False
        else:
            print('太撑了,吃不下了!')
运行:
>>> fish = Fish()
>>> fish.move()
我的位置是: 3 0
>>> fish.move()
我的位置是: 2 0
>>> goldfish = Goldfish()
>>> goldfish.move()
我的位置是: 4 9
>>> goldfish.move()
我的位置是: 3 9
>>> shark = Sharkfish()
>>> shark.eat()
吃货的梦想就是天天有的吃^_^
>>> shark.eat()
太撑了,吃不下了!
>>> shark.move()  #无法访问到父类的__init__()方法中的x变量
AttributeError: 'Sharkfish' object has no attribute 'x'

覆盖属性或方法问题优化:
问题:针对子类属性或方法覆盖父类属性或方法的情况,导致子类无法访问父类中被覆盖的属性
(1) 调用未绑定的父类的方法
(2) 使用super方法(推荐)
举例
def __init__(self):
Fish.__init__(self)  #调用未绑定的父类的方法,相当于>>>Fish.__init__(Sharkfish)
self.hungry = True
运行:
>>> shark = Sharkfish()
>>> shark.move()
我的位置是: -1 2
>>> shark.move()
我的位置是: -2 2

举例
def __init__(self):
super().__init__()  #使用super方法解决
self.hungry = True
运行:
>>> shark = Sharkfish()
>>> shark.move()
我的位置是: 8 3
>>> shark.move()
我的位置是: 7 3

多重继承
class DerivedClassName(Base1, Base2, Base3, ...):
...
#建议少用,有可能会导致不可预见的bug(不可预见最麻烦)
>>> class Base1:
def fool(self):
print('我是fool,我为Base1代言...')
>>> class Base2:
def fool2(self):
print('我是fool2,我为Base2代言...')
>>> class C(Base1, Base2):
pass
>>> c = C()
>>> c.fool()
我是fool,我为Base1代言...
>>> c.fool2()
我是fool2,我为Base2代言...

10. 组合
class Turtle:
    def __init__(self, x):
        self.num = x
class Fish:
    def __init__(self, x):
        self.num = x
class Pool:
    def __init__(self, x, y):  #组合的方式嵌套class
        self.turtle = Turtle(x)
        self.fish  = Fish(y)
    def print_num(self):
        print('水池里总共有乌龟 %d 只,小鱼 %d 条!' % (self.turtle.num, self.fish.num))
运行:
>>> pool = Pool(1, 10)
>>> pool.print_num()
水池里总共有乌龟 1 只,小鱼 10 条!

11. 类、类对象、示例对象
类定义    C
类对象    C
实例对象  a  b  c

举例
>>> class C:   #C, 既是类,也是类对象
count = 0
>>> a = C()    #a,实例对象
>>> b = C()    #b,实例对象
>>> c = C()    #c,实例对象
>>> a.count
0
>>> b.count
0
>>> c.count
0
>>> c.count += 10
>>> c.count
10
>>> a.count
0
>>> b.count
0
>>> C.count    #C,作为类对象
0
>>> C.count += 100    #C,作为类对象
>>> a.count
100
>>> b.count
100
>>> c.count
10

(1) 当属性名与方法名冲突,会导致方法不能正常调用。
(2) 一般遵循规则:属性名用英文名词,方法名用英文动词。
(3) python严格要求方法需要有实例才能被调用,即绑定的概念。

举例
>>> class C:
def x(self):
print('X-man!')
>>> c = C()
>>> c.x()
X-man!
>>> c.x = 1
>>> c.x
1
>>> c.x()  #方法名字被属性名字覆盖,调用出错
TypeError: 'int' object is not callable
>>> class BB:
def printBB():
print('no zuo no die.')
>>> BB.printBB()
no zuo no die.
>>> #没有self,也没有将类实例化
>>> bb = BB()
>>> bb.printBB()
Traceback (most recent call last):
  File "<pyshell#187>", line 1, in <module>
    bb.printBB()
TypeError: printBB() takes 0 positional arguments but 1 was given
>>> class CC:
def setXY(self, x, y):
self.x = x;
self.y = y
>>> class CC:
def setXY(self, x, y):
self.x = x
self.y = y
def printXY(self):
print(self.x, self.y)
>>> dd = CC()
>>> dd.__dict__
{}  #返回空的字典类型
>>> CC.__dict__
mappingproxy({'printXY': <function CC.printXY at 0x0000020483176EA0>, '__doc__': None, '__dict__': <attribute '__dict__' of 'CC' objects>, 'setXY': <function CC.setXY at 0x0000020483176E18>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'CC' objects>})  #使用类对象显示类的属性详情
>>> dd.setXY(4, 5)
>>> dd.__dict__
{'y': 5, 'x': 4}  #将实例对象dd使用类的属性详情实例化了
>>> # setXY(self, x, y) <==> dd.setXY(dd, x, y)
>>> del CC
>>> ee = CC()
NameError: name 'CC' is not defined
>>> dd.printXY()
4 5  #类中定义的属性是静态的,类的实例对象中也会静态存储,所以实例对象dd正常存在。

12. 类与对象的内置函数
issubclass

功能:测试一个类是否是另外一个类的子类
issubclass(class, classinfo)
(1) 一个类被认为是其自身的子类
(2) classinfo可以是类对象的元组,只要class属于其中任何一个候选类的子类,则返回True
举例
>>> class A:
pass
>>> class B(A):
pass
>>> issubclass(B, A)
True
>>> issubclass(B, B)
True
>>> issubclass(B, object)  #object是所有类的基类
True
>>> class C:
pass
>>> issubclass(B, C)

isinstance
功能:测试一个对象是否是一个类的实例对象
isinstance(object, classinfo)
(1) object为类的实例对象,如果不是类的实例对象,永远返回False
(2) 如果第二个参数不是类或者由类对象组成的元组,会抛出一个TypeError异常
举例
>>> class A:
pass
>>> class B(A):
pass
>>> class C:
pass
>>> b1 = B()
>>> isinstance(b1, B)
True
>>> isinstance(b1, A)
True
>>> isinstance(b1, C)
False
>>> isinstance(b1, (A, B, C))  #b1对象是否在A/B/C里面,答案是True
True

hasattr
功能:测试一个对象里面是否有指定的属性
hasattr(object, name)
(1) object 对象名, name 是属性名(需要用引号引起来,否则报错)

getattr
功能:返回对象指定的属性值
getattr(object, name[, default])
(1) 如果属性值不存在打印default,没有default则抛出异常

setattr
功能:设置对象中指定属性的值,如果属性不存在则创建并赋值
setattr(object, name, value)

delattr
功能:删除对象中指定的属性,如果属性不存在则抛出异常
delattr(object, name)

举例
>>> class C:
def __init__(self, x=0):
self.x = x
>>> c1 = C()
>>> hasattr(c1, 'x')  #测试对象属性是否存在
True
>>> hasattr(c1, x)\
NameError: name 'x' is not defined
>>> getattr(c1, 'x')  #获取对象属性的值
0
>>> getattr(c1, 'y')
AttributeError: 'C' object has no attribute 'y'
>>> getattr(c1, 'y', '您所访问的属性不存在!')  #设置default默认提示语
'您所访问的属性不存在!'
>>> setattr(c1, 'y', 100)  #设置对象属性的值
>>> getattr(c1, 'y')
100
>>> delattr(c1, 'y')  #删除对象属性的值
>>> delattr(c1, 'y')
Traceback (most recent call last):
  File "<pyshell#264>", line 1, in <module>
    delattr(c1, 'y')
AttributeError: y

property
功能:设置一个定义好的属性,通过对象属性来设置对象属性
property(fget=None, fset=None, fdel=None, doc=None)
(1) fget获取属性的方法, fset设置属性的方法, fdel删除属性的方法
举例:
>>> class C:
def __init__(self, size=10):
self.size = size
def getSize(self):
return self.size
def setSize(self, value):
self.size = value
def delSize(self):
del self.size
x = property(getSize, setSize, delSize)
>>> c1 = C()
>>> c1.getSize()
10
>>> c1.x
10
>>> c1.x = 18
>>> c1.x
18
>>> c1.getSize()
18
>>> c1.size
18
>>> del c1.x
>>> c1.size    #x与size相当于相互引用关系,删除其中一个另一个即不能访问
AttributeError: 'C' object has no attribute 'size'

阅读更多
上一篇python笔记(四)
下一篇python中的SQLite数据库
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭