python提高2
1.多继承中的MRO顺序
一个类可以有多个父类,多继承,难点:super
python里用的多的,重写,重新覆盖父类的方法
用父类名字调用父类,浪费资源
用super是先到mro元组里查找对应的调用,再从这个往后一个调用
c3算法确定mor元组。保证每个类只调用一次
class Parents(object):
a = 100
def __init__(self, name, *args, **kwargs):
print('Parent-------------->Begin')
self.name = name
print('Parent-------------->End')
class Son1(Parents):
#这里用*args,**kwargs,不定长参数,是为了避免多继承的报错
def __init__(self, age, name, *args, **kwargs):
print('Son1------------>Begin')
self.age = age
# Parents.__init__(self, name)
super(Son1, self).__init__(name, *args, **kwargs)
print('Son1------------>End')
class Son2(Parents):
def __init__(self, sexy, name, *args, **kwargs):
print('Son2------------>Begin')
self.sexy = sexy
# Parents.__init__(self, name)
super(Son2, self).__init__(name, *args, **kwargs)
print('Son2------------>End')
class GrandSon(Son1,Son2):
def __init__(self, name, sexy, age):
print('Grandson---------->Begin')
# Son1.__init__(self, age, name)
# Son2.__init__(self, sexy, name)
super(GrandSon, self).__init__(age, sexy, name)
print('Grandson---------->End')
if __name__ == '__main__':
print(GrandSon.__mro__)
gs = GrandSon('李华', '男', 18)
print('姓名:', gs.name)
print('性别:', gs.sexy)
print('年龄', gs.age)
输出:
(<class '__main__.GrandSon'>, <class '__main__.Son1'>, <class '__main__.Son2'>, <class '__main__.Parents'>, <class 'object'>)
Grandson---------->Begin
Son1------------>Begin
Son2------------>Begin
Parent-------------->Begin
Parent-------------->End
Son2------------>End
Son1------------>End
Grandson---------->End
姓名: 李华
性别: 男
年龄 18
2.*args **kwargs
参数不确定存不存在,可以设置这个,* args元组,**kwargs字典
- 相当于把元组拆开
- *相当于把字典拆开
def a_function(a, b, *args, **kwargs):
print(a, b)
print(args)
print(kwargs)
a_function(1, 2, 1, 2, 3, 4, hbh='sad1', asdhjk='121')
>>>
>>>1 2
(1, 2, 3, 4)
{'hbh': 'sad1', 'asdhjk': '121'}
3.类属性,实例属性
实例属性属于对象
类属性属于类
类属性在内存中只保存一份
实例属性在每个对象中都要保存一份
实例方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。
实例方法:由对象调用;至少一个self参数;执行实例方法时,自动将调用该方法的对象赋值给self;
类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类赋值给cls;
静态方法:由类调用;无默认参数;
类里,def外,类属性;是实例对象共有的属性
实例对象的,自己特有的,是实例属性
创建对象其实是两步:调用__new__ 创建对象,申请内存空间
调用__init__对对象初始化
实例方法 带self
类方法可以修改类属性,传出类对象,把self改为cls
静态方法,无默认参数,@staticmethod
4.property属性
重点,@property,把函数变成了属性,return一个值,在实例方法的基础上加上property装饰器变为属性,并且参数只有一个self,调用的时候方法不用加括号啦
就是为了方便使用,将方法变为属性调用
@在python里叫语法糖。
创建property装饰器
方法前加@property语法糖?,取得属性值;@方法名.setter 设置值;@方法名.deleter删除属性
用类属性创建property
属性名 = property(方法名)
bar = property(get_bar,set_bar,del_bar,‘doc…’)
通过property属性更容易,简化流程
私有属性的get和set方法可以取修改私有属性的值,property可以来升级get和set方法
python中没有绝对的私有属性
访问不了,是因为python解释器把其名字改为_类名__私有属性名
这叫名字重整。
5.面向对象设计
6.with上下文管理器 context
任何实现了__enter__() 方法和 exit()就是上下文管理器
with 上下文管理器 as f 就把enter()返回的给f ,遇到异常自动调用exit方法
对于系统资源, 文件打开,socket,都是有限的,如果打开了,一定要关闭
或者导入contextlib库里的contextmanger模块,用contextmanager模块修饰方法。在yeid前的就是正常执行代码,yield之后的就是异常执行代码
#任何实现了 __enter__()和__exit__()的方法的对象都是上下文管理器
class File(object):
def __init__(self, filname, mode):
self.filename = filname
self.mode = mode
def __enter__(self):
print('entering')
self.f = open(self.filename, self.mode)
return self.f
def __exit__(self, *args):
print('exit')
self.f.close()
with File('a.txt', 'w') as f:
print('writing')
f.write('hello world')
'''
这里实现了这个功能呢,上下文管理器只要有enter和exit的魔法方法就是上下文管理器
with就可以用上下文管理器,enter正常执行的代码返回的值给f
如果执行过程中发生异常,就执行exit里的代码
'''
#上下文管理器的推荐方式,导入contextlib库,通过yield将函数分为上下文两部分,上面一部分是正常执行的部分,下面是异常处理部分
from contextlib import contextmanager
@contextmanager
def file(file_name, mode):
f = open(file_name, mode)
yield f
f.close()
with file('a.txt','w') as f:
f.write('hello world')
在类里用就是如下的效果
from contextlib import contextmanager
class File(object):
def __init__(self, filname, mode):
self.filename = filname
self.mode = mode
@contextmanager
def file(self):
print('entering')
self.f = open(self.filename, self.mode)
yield self.f
print('closing')
self.f.close()
f = File('a.txt', 'w')
with f.file() as f:
print('writing')
f.write('hello world')