58.丰富的else语句
1)与if搭配
2)与for和while搭配(只有当循环顺利完成后才可以进入else)
def showMaxFactor(num):
count=num//2
while count>1:
if num%count==0:
print('%d的最大的约数是%d'%(num,count))
break
count=-1
else:
print('%d是素数!'%num)
num= int(input('请输入一个数:')
showMaxFactor(num)
3)与try配合--能捕获到异常
try:
int('abc')
except ValueError as reason:
print('出错啦'+str(reason))
else:
print('没有异常')
运行如下:
>>>
================= RESTART: C:/Users/yangfei/Desktop/digui.py =================
出错啦invalid literal for int() with base 10: 'abc'
4)与try配合--没有异常,进入else语句
try:
int(123)
except ValueError as reason:
print('出错啦'+str(reason))
else:
print('没有异常')
运行如下:
>>>
================= RESTART: C:/Users/yangfei/Desktop/digui.py =================
没有异常
59.with语句:自动关闭文件
1)以w的形式打开一个未存在的文件。等于新建了一个文件,如果不继续写入文本,则文件内容为空,继续读出该文件内容则会报错
>>> f=open('testa.txt','w')
>>> for each_line in f:
print(each_line)
Traceback (most recent call last):
File "", line 1, in
for each_line in f:
io.UnsupportedOperation: not readable
>>> f.close()
>>> f=open('testa.txt')
>>> f.read()
''
2)用try捕获not readable的异常
try:
f=open('data.txt','w')
for each_line in f:
print(each_line)
except OSError as reason:
print('出错啦'+str(reason))
finally:
f.close()
运行如下
>>>
================= RESTART: C:/Users/yangfei/Desktop/digui.py =================
出错啦not readable
3)用with代替实现finally语句
try:
with open('data.txt','w') as f:
for each_line in f:
print(each_line)
except OSError as reason:
print('出错啦'+str(reason))
60.GUI编程
翻译版本文档:http://bbs.fishc.com/forum.php?mod=viewthread&tid=46069&extra=page%3D1&page=1
61.对象
对象=属性+方法
用类类创建一个对象
类名用大写字母开头
1)定义一个类
class Turtle:
color='green'
weight=10
legs=4
shell=True
mouth='大嘴'
def climb(self):
print('努力爬啊爬')
def run(self):
print('努力跑')
def bite(self):
print('咬人')
def eat(self):
print('吃吃吃')
def sleep(self):
print('困了睡觉')
2)类创建一个对象
================= RESTART: C:/Users/yangfei/Desktop/digui.py =================
>>> tt=Turtle() #创建一个对象tt
>>> Turtle() #其实这个时候也生成了一个对象,只不过没有指针来引用,所以会被python回收机制给回收了
<__main__.Turtle object at 0x0000012C2E970DA0>
3)调用对象方法
>>> tt.climb()
努力爬啊爬
>>> tt.bite()
咬人
>>> tt.sleep()
困了睡觉
4)oo的特征
面向对象=oo=Object Oriented
面向对象编程=oop=Object Oriented program
【封装】对象封装了属性和方法,信息隐蔽技术
【继承】子类自动共享父类属性和方法
>>> class Mylist(list): #定义一个类Mylist,但是他集成list这个类,说明可以具备list的属性和方法
pass
>>> list2=Mylist() #用Mylist来实例化一个对象list2
>>> list2.append(9) #由于Mylist是具有list的属性和方法,所以由Mylist生成的对象可以使用append方法
>>> list2.append(5)
>>> list2
[9, 5]
>>> list2.sort()
>>> list2
[5, 9]
【多态】不同对象对同一方法响应不同的行动
移动这个操作,老虎是快速奔跑,袋鼠是跳着走,乌龟是慢慢爬
>>> class A:
def fun(self):
print('我是小A')
>>> class B:
def fun(self):
print('我是小B')
>>> a=A()
>>> b=B()
>>> a.fun()
我是小A
>>> b.fun()
我是小B
以上两个类的实例化对象调用同一个fun函数反应是不一样的
62.面向对象编程
1)self是什么
类是图纸,由类实例化后的对象才是真正可以住人的房子
一个图纸可以造出成千上万的房子,每个房子有自己的主人
每个人只能回自己的家,教育自己的孩子,使用自己家的设施
所以self就是每个房子的门牌号
同一个类可以生成无数个对象,对象都长得很相似
当一个对象的方法被调用的时候,对象会将自身作为参数传给self参数,接受到这个self的时候,python系统就知道是哪一个对象在调用方法了
>>> class Boll:
def setName(self,name):
self.name=name
def kick(self):
print('我叫%s,该死的,谁替我。。。'% self.name)
>>> a=Boll()
>>> a.setName('球A')
>>> b=Boll()
>>> b.setName('球B')
>>> c=Boll()
>>> c.setName('球C')
>>> a.kick()
我叫球A,该死的,谁替我。。。
>>> b.kick()
我叫球B,该死的,谁替我。。。
>>> c.kick()
我叫球C,该死的,谁替我。。。
#只要知道在类的定义时候,在函数中写入第一个参数self就OK
2)魔法方法
python的对象天生拥有一些神奇的方法,他们是面向对象的python的一切。。。
可以给类增加魔力的方法
如果你的对象实现了这些方法中的某一个,那么这个方法就会在特殊的情况下被python所调用,而这一切都是自动发生的。。。
这些魔力方法被双下划线所包围
【__init__(self)】构造方法
魔力:只要实例化一个对象的时候,这个方法会在对象被创建时候被调用
【__init__(self,param1,param2..)】
其实实例化对象时候是可以传入参数的,这些参数会自动的传入到__init__方法中
可以通过重写这个方法来自定义对象的初始化操作,这些参数还可以默认参数
>>> class Ball:
def __init__(self,name):
self.name=name
def kick(self):
print('我叫%s,该死的,谁踢我。。。'%self.name)
>>> b=Ball('hhaha')
>>> b.kick()
我叫hhaha,该死的,谁踢我。。。
3)公有和私有:
对象的属性和方法都是公有的,可以利用点操作符来使用
>>> class Person:
name='ahah'
>>> p=Person
>>> p.name
'ahah'
name mangling 名字重造方法来改造公有属相到私有属性:在Python中定义私有变量只需要在变量名或函数名前加上‘__'两个下划线,那么这个函数或变量就会变为私有的了
>>> class Person:
__name='haha'
>>> p=Person
>>> p.name
Traceback (most recent call last):
File "", line 1, in
p.name
AttributeError: type object 'Person' has no attribute 'name' #name现在在定义时候前面多了两个下划线,表示这个属性是私有属性,通过类外部是不可以访问的,所以报错
私有属性在类的内部是可以访问的:通过类内部的getName方法来获取内部私有属性
>>> class Person:
__name='haha'
def getName(self):
return self.__name
>>> P=Person()
>>> P.__name
Traceback (most recent call last):
File "", line 1, in
P.__name
AttributeError: 'Person' object has no attribute '__name'
>>> P.getName()
'haha'
Python的伪私有:可以通过以下改造私有属性name的方式实现访问私有属性
>>> P._Person__name
'haha'
63.继承
我们试图模拟一个场景,里边有一只乌龟和十条鱼,乌龟通过吃鱼来补充体力,当乌龟体力消耗殆尽或者鱼被吃光则游戏结束
现在我们想要扩展游戏,给鱼类进行细分,有金枪鱼(Goldfish)、鲤鱼(Carp)、三文鱼(Salmon)、还有鲨鱼(Shark)
那么我们就在思考一个问题:能不能不要每次都从头到尾重新定义一个新的鱼类呢?因为我们知道大部分鱼的属性和方法是相似的
class DerivedClassName(BaseClassName):
其中BaseClassName是基类、父类或超类
其中DerivedClassName是子类
子类可以继承父类的任何属性和方法
>>> class Parent:
def hello(self):
print('正在调用父类的方方法')
>>> class Child(Parent):
pass
>>> p=Parent()
>>> p.hello()
正在调用父类的方方法
>>> c=Child()
>>> c.hello()
正在调用父类的方方法
>>>
如果子类中定义与父类同名的方法或属性,会自动覆盖父类对应的方法或属性
>>> 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()
正在调用子类方法
【鱼的例子代码】
1)定义各种鱼类
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('吃货的梦想就是天天有的吃')
self.hungry=False
else:
print('太撑了,吃不下了!')
2)实例化各种鱼对象并调用与对象的方法:
>>>
====================== RESTART: D:/python/3.5.1/fish.py ======================
>>> fish=Fish()
>>> fish.move()
我的位置是: 4 5
>>> goldfish=Goldfish()
>>> goldfish.move()
我的位置是: 3 1
>>> goldfish.move()
我的位置是: 2 1
>>> goldfish.move()
我的位置是: 1 1
>>> goldfish.move()
我的位置是: 0 1
>>> goldfish.move()
我的位置是: -1 1
>>> shark=Shark()
>>> shark.eat()
吃货的梦想就是天天有的吃
>>> shark.eat()
太撑了,吃不下了!
>>> shark.move()
Traceback (most recent call last):
File "", line 1, in
shark.move()
File "D:/python/3.5.1/fish.py", line 9, in move
self.x-=1
AttributeError: 'Shark' object has no attribute 'x'
#当调用鲨鱼的move方法时候,虽然鲨鱼也继承了fish这个大类,按道理应该有move这个方法,但是由于在定义shark这个子类的时候,重写的__init__方法所以导致父类的__init__被覆盖,也就是当使用move时候需要的x参数y参数都不会找到
#优化以下类定义方法,在shark子类重写init时候把xy定义语句也重写写一遍:
class Shark(Fish):
def __init__(self):
self.hungry=True
self.x=r.randint(0,10)
self.y=r.randint(0,10)
def eat(self):
if self.hungry:
print('吃货的梦想就是天天有的吃')
self.hungry=False
else:
print('太撑了,吃不下了!')
#此时再调用shark对象的move就不会报错了:
====================== RESTART: D:/python/3.5.1/fish.py ======================
>>> shark=Shark()
>>> shark.move()
我的位置是: 8 9
3)除了上述直接再子类的构造函数中重写父类构造函数中语句以免子类构造函数覆盖父类构造函数引发错误,的笨办法外,可以利用super函数和调用未绑定的父类方法
【1】调用未绑定的父类方法
改写类的定义
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):
Fish.__init__(self)
self.hungry=True
def eat(self):
if self.hungry:
print('吃货的梦想就是天天有的吃')
self.hungry=False
else:
print('太撑了,吃不下了!')
使用对象调用move方法
====================== RESTART: D:/python/3.5.1/fish.py ======================
>>> shark=Shark()
>>> shark.move()
我的位置是: -1 4
【2】使用super函数:
1)改写Shark子类
class Shark(Fish):
def __init__(self):
super().__init__() #super函数自动找出父类及父类方法
self.hungry=True
def eat(self):
if self.hungry:
print('吃货的梦想就是天天有的吃')
self.hungry=False
else:
print('太撑了,吃不下了!')
2)运行脚本
====================== RESTART: D:/python/3.5.1/fish.py ======================
>>> shark=Shark()
>>> shark.move()
我的位置是: 2 4
64.多重继承
>>> class Base1:
def fool(self):
print('我是fool,我为Base1代言...')
>>> class Base2:
def fool2(self):
print('我是fool2,我为Base2代言。。。')
>>> class C(Base1,Base2):
pass
>>> c=C()
>>> c.fool2()
我是fool2,我为Base2代言。。。
>>> c.fool()
我是fool,我为Base1代言...