面向对象
面向对象应该是我们学习python的重中之重。老师说面向对象的程序语言编写显得更加的人性化,更加的易于人们接受和理解,所以这周我们主要是对面向对象编程的一次深入研究。
面向对象编程方法,通过class来定义一个类,再在这个类中用def来定义一个方法,而且它必须有一个额外的第一个参数名称,按照习惯我们一般写成self,当然换做其他的例如runoob也是可以的:
class Example(object):
def one(self):
...
我们在定义类的时候往往都会有些初始状态,会有些参数,这时候我们就需要
def __init__(self,x,y,z):
self._x = x
self._y = y这样我们在进行类的实例化操作时,便会自动调用这个方法。当参数是不定的时候我们可以用
*args
,或者关键字**kwargs
的方法来进行参数的定义。
父类、子类之间的联系
class Father(object):
def __init__(self, x, y, z):
self._x = x
self._y = y
self._z = z
clsaa Son(Father):
def __init__(self, x, y, t):
super().__init(x, y)
self._t = t
由上例中可以看出,我们首先创建了一个类叫Father,之后又创建了一个类叫Son,Son这个类可以继承Father的相同属性,Son自己也可以有自己的私有属性,所以称Father为父类,Son为子类。
同样的道理,子类也是可以继承父类中定义的方法的,同时也可以进行覆写。子类调用经过覆写之后的方法,输出的是子类中的方法,父类调用的则仍然是没有进行覆写的方法。如果同时有多个子类进行了方法的覆写,则各子类的输出是各经过改写的方法的输出。
包装器(wrapper)/装饰器(decorator)
def record(fn):
def wrapper(*args,**kwargs):
print('准备执行%s函数' % fn.__name__)
print(args)
print((kwargs))
# 此行代码在执行被装饰的函数
# 在这行代码的前后我们可以附加其他的代码
# 这些代码可以让我们正在执行函数时做一些额外的工作
val = fn(*args,**kwargs)
print('%s函数执行完成' % fn.__name__)
print('返回了%d' % val)
# 返回被装饰的函数的执行结果
return val
return wrapper
# 通过装饰器修饰f函数 让f函数在执行过程中可以做更多地额外的操作
@record
def f(n):
if n == 0 or n == 1:
return 1
return n * f(n - 1)
if __name__ == '__main__':
print(f(n))
- 当上述程序的n取值为1时,其输出结果为:
准备执行f函数
(1,)
{}
f函数执行完成
返回了1
1
- 由此可知,在被装饰的代码执行之前,会执行装饰器的代码,这样我们可以让被装饰的函数在执行过程中做更多额外的操作。python一向要求:高内聚,低耦合,我们可以通过定义一个函数的第二个参数是另一个函数达到这个目的,这样可以使得该函数不与某种特定的二元运算耦合起来。这样的运算函数可以使用lambda函数(匿名函数)来实现,例如加法:
lambad x, y : x + y
- 我们在定义一个类的时候,往往会将其中的参数作为私有参数,不允许外部调用:
calss Drs(self):
def __init__(self, x, y):
self._x = x
self._y = y
- 一个下划线开头或者两个下划线开头指这个属性是这个类私有的,外部不能调用(实际上python中是不能够保证的,所以这个只是告诉别人这个是私有的,不能随便修改)。我们在绑定属性时,如果直接将属性暴露出去,虽然写起来很容易,但是没有办法检查参数,导致属性会被随意修改,所以这里我们需要
@property装饰器
,这个装饰器的意义是将一个方法变成属性调用。
@property
def x(self):
return self._x
- 而通过
@property装饰器
我们还可以获得一个@x.setter装饰器
,从而可以将x进行属性赋值:
@x.setter
def x(self,a):
self._x = a
这里的
one.x(b)
输出就为self._x = b
。简而言之,@property``@.setter
分别是属性访问器和属性修改器,@.deleter则是属性删除器
我们还有静态方法
@staticmethod
和类方法@classmethod
这两种包装器用来对类进行包装,不过在下学艺不精,不是太怎么懂这两者的区别,就暂借网上的解释了:- 普通方法(simple) def f(self, x): 的第一个参数 self 绑定的对象是实例对象 a, 第二个参数是 x ;
- 类方法(classmethod) def f(cls, x): 的第一个参数 cls 绑定的对象是类 A , 第二个参数是 x ;
- 静态方法(staticmethod) def f(x): 的第一个参数就是传参 x 自己.
当定义类的时候,会有些不能存在的情况,如果发生了,可以使用raise ValueError()来引发错误,并将错误简单告诉使用者。
- python没有从语言层面支持抽象类的概念.我们可以通过abc模块来制造抽象类的效果,
from abc import ABCMeta, abstractmethod
通过在定义类的时候通过制定metaclass = ABCMeta
可以将类声明为抽象类。抽象类是不能创建对象的,抽象类存在的意义是专门拿给其他类继承abc模块中,还有一个包装器abstractmethod通过这个包装器可以将方法包装为抽象方法,必须要求子类进行重写,如果子类没有进行重写则直接报错。__slots__
则是限制类的绑定属性的,__slots__ = ('name', 'age')
这个就限制类只能绑定name``age
,如果绑定其他属性的话就会报错。
异常机制
- 我们在程序的运行过程中往往是会遇到问题的,而且不是所有的问题都能够在调试程序的时候发现的,所以我们可以将一些容易发生问题的程序放在
try:
下进行运行,再通过except Error
来进行错误的捕获,例:
def main():
filenames = ('lalala.txt', 'lala.txt', 'la.txt')
fs_list = []
try:
# 把有可能出状况(在执行时有风险)的代码放在try代码块保护执行
for filename in filenames:
fs_list.append(open(filename, 'w', encoding='utf-8'))
for number in range(1,10000):
if sushu(number):
if number < 100:
fs_list[0].write(str(number) + '\n')
elif number < 1000:
fs_list[1].write(str(number) + '\n')
elif number < 10000:
fs_list[2].write(str(number) + '\n')
except IOError:
# 如果try中出现了状况就通过except来捕获错误(异常)进行对应的处理
print('读写文件发生错误')
else:
# 如果没有出状况,那么可以把无风险的代码放到else中执行
pass
finally:
# 不管程序正常或异常,总是会执行。这里是最好的释放外部资源的位置
for fs in fs_list:
fs.close()
print('操作完成')
Python中文件的读取和改写
def main():
try:
with open('lalala.txt', 'r', encoding='utf-8') as fs:
# 这种方法打开,会在之后自动将其关闭
mylist = fs.readlines()
print(mylist)
except FileNotFoundError:
print('指定的文件无法打开.')
print('程序执行结束.')
def main():
try:
fs = open('lalala.txt', 'r', encoding='utf-8')
content = fs.read()
for line in fs:
print(line,end='')
time.sleep(0.5)
print(content)
fs.close()
# 这个方法必须进行手动关闭文件
except FileNotFoundError:
print('指定的文件无法打开.')
print('程序执行结束.')
- 我们的python是面向网络的,所以我们需要学习json的内容,用json与文件的读取、改写相结合,在此,我就将老师课堂上的例子放在这好了,毕竟我也不会:
import requests
import json
def main():
resp = requests.get()
mydict = json.loads(resp.text)
for tempdict in mydict['newslist']:
pic_url = tempdict['picUrl']
resp = requests.get(pic_url)
filename = pic_url[pic_url.rfind('/') + 1:]
try:
with open(filename, 'wb') as fs:
fs.write(resp.content)
except IOError as e:
print(e)
- 作为周五最后学的知识,以及作为下一周的重点的知识内容,必定需要我们自己多多学习领悟。
Pygame
- 本周我们主要学习了使用pygame来进行游戏的编写,主要使用了面对对象的编写方法,融合使用了函数,嵌套定义,返回值,参数,可变参数,关键字参数,等这三周学习的内容。本人愚钝,并不能完全领会,只能识其皮毛。
心得
- 跟第二周的感觉其实没有多大变化,因为这周的pygame主要是将前两周的知识点进行了融汇升华,从而让学生们自己领悟。但因为是融合的所有知识点,所以难度也是肯定的,而且pygame的很多操作我并不会,所以我卡壳的时间也比较长。现在的感觉就是,给我个代码,我大概能看懂,但是自己写的话可能需要花费很长时间,也有可能解决不了,特别是下周还需要进行考核,心中有点慌,只能用心将这三周的知识认真看懂了。