python修炼——python提高!
今日内容概述:
多继承及 MRO 顺序 | **args、**kwargs | 类对象、实例对象、类属性、实例属性、实例方法、静态方法、类方法 | 内置方法 | property属性 | 魔法属性 | 面向对象设计 | with 上下文管理器 | 面向对象回顾 | GIL 全局解释器锁回顾
一、多继承及 MRO 顺序
使用父类名调用:父类的父类会执行多次
super在多继承中的作用:
__mro__ 内置属性: 多继承时,输出调用父类方法是顺序 由C3 算法决定
使用 super 调用:父类的父类只需执行一次
二、*args **kwargs
多值参数 拆包、解包
形参时是接收:
*args :接收的是一个元组
**kwargs:接收的是一个字典,由键值对的方式给值
实参时是拆包:
*args:把元组拆成一个个元素值
**kwargs:把字典拆成键值对
三、类对象、实例对象、类属性、实例属性、实例方法、静态方法、类方法
- 类属性修改只能由类名来操作
- 实例对象可以用类属性,不能修改,修改就相当于新建了一个实例属性
- @staticmethod @classmethod
- 调用类相关的内容和静态方法推荐使用类名来调用
- 类属性在内存中保存一份
- 实例属性在每个对象中都要保存一份
- 实例方法:由对象调用;至少一个self参数;执行实例方法时,自动将调用该方法的对象赋值给self;
- 类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类赋值给cls;
- 静态方法:由类调用;无默认参数;
四、内置方法
- 不需要程序员调用,python解释器触发某个条件时调用
- def __xxx__(self):
私有类属性可以通过 类名.类名_属性名 来访问
五、property属性
使用:在实例方法的基础上添加 @property 装饰器,
可以像调用一个实例属性一样调用实例方法 调用时不需要括号
- 这个实例方法不要多写参数
- 使用 property 后,调用时不需要传递参数。
property 属性的两种方式
1.装饰器方式
- @property: 获取
- @price.setter: 设置 必须两个参数
- @price.deleter:删除
- 经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法
- 新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
由于新式类中具有三种访问方式,我们可以根据它们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
# ############### 定义 ###############
class Goods:
"""python3中默认继承object类
以python2、3执行此程序的结果不同,因为只有在python3中才有@xxx.setter @xxx.deleter
"""
@property
def price(self):
print('@property')
@price.setter
def price(self, value):
print('@price.setter')
@price.deleter
def price(self):
print('@price.deleter')
# ############### 调用 ###############
obj = Goods()
obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
obj.price = 123 # 自动执行 @price.setter 修饰的 price 方法,并将 123 赋值给方法的参数
del obj.price # 自动执行 @price.deleter 修饰的 price 方法
2.property-类属性
建议使用这一种
property方法中有个四个参数
- 第一个参数是方法名,调用 对象.属性 时自动触发执行方法
- 第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
- 第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法
- 第四个参数是字符串,调用 对象.属性.doc ,此参数是该属性的描述信息
class Foo(object):
def get_bar(self):
print("getter...")
return 'laowang'
def set_bar(self, value):
"""必须两个参数"""
print("setter...")
return 'set value' + value
def del_bar(self):
print("deleter...")
return 'laowang'
BAR = property(get_bar, set_bar, del_bar, "description...")
obj = Foo()
obj.BAR # 自动调用第一个参数中定义的方法:get_bar
obj.BAR = "alex" # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入
desc = Foo.BAR.__doc__ # 自动获取第四个参数中设置的值:description...
print(desc)
del obj.BAR # 自动调用第三个参数中定义的方法:del_bar方法
六、魔法属性
私有属性,名字重整
魔法属性:
__dict__:检查类和对象中的所有属性
__doc__ : 查看类的描述信息
__module__ :表示当前操作的对象在那个模块
__class__: 表示当前操作对象的类是什么
__init__: 初始化方法,通过类创建对象时,自动执行
__del__: 当对象在内存中释放的时候,会自动调用
__call__: 对象后面加括号,会触发执行
__str__: 如果类中定义了 __str__ 方法,那么在打印对象是,默认输出该方法的放回值(没有该方法,会返回对象的地址)
__getitem__、__setitem__、__delitem__: 用于索引操作,如字典。以上分别表示获取、设置、删除
七、面向对象设计
- 继承 - 是基于Python中的属性查找(如X.name)
- 多态 - 在X.method方法中,method的意义取决于X的类型
- 封装 - 方法和运算符实现行为,数据隐藏默认是一种惯例
八、with 上下文管理器
使用 with 打开文件,当离开 with 代码块的时候,系统会自动调用 close() 方法,可以避免使用普通方法打开文件时出现异常无法关闭文件的现象。
上下文管理器
任何实现了 __enter__() 和 __exit__() 方法的对象都可称之为上下文管理器,上下文管理器可以使用 with 关键字。
class File():
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
print("entering")
self.f = open(self.filename, self.mode)
return self.f
def __exit__(self, *args):
print("will exit")
self.f.close()
with File('out.txt', 'w') as f:
print("writing")
f.write('hello, python')
实现上下文管理的另一种方式
"""
Python 还提供了一个 contextmanager 的装饰器,更进一步简化了上下文管理器的实现方式。通过 yield 将函数分割成两部分,yield 之前的语句在 __enter__ 方法中执行,yield 之后的语句在 __exit__ 方法中执行。紧跟在 yield 后面的值是函数的返回值。
"""
from contextlib import contextmanager
@contextmanager
def my_open(path, mode):
f = open(path, mode)
yield f
f.close()
with my_open('out.txt', 'w') as f:
f.write("hello , the simplest context manager")
面向对象回顾
面向对象概念
- 面向过程:做一件事从头到尾都要关心
- 面向对象:做一件事不关心过程,只关心结果
- 类:一类事物,一个抽象的概念
- 对象:是类的具象化
- 特征(属性)相当于一个变量、功能行为(方法)相当于函数
封装继承多态
封装:
- 高内聚:把相关功能尽量放在一个类中
- 低耦合
继承:
- 概念:子类可以拥有父类的属性和方法
- 作用:减少代码的书写,提高代码阅读性
- 单继承:可以一直向下传递
- 多继承:一个子类可以继承多个父类
- 方法重写
多态:
- 一个对象有多种形态
- 条件:继承和方法的重写
- 增强代码的灵活性
GIL 全局解释器锁
多任务是指同一时刻可以执行多个任务。
协程开销最小,线程在中,进程消耗最大
协程基于线程,线程基于进程
GIL 同一时刻只允许一个线程在执行。假的并发。多进程每个核消耗占一半,一共100%。
这个问题和python语言没有关系
只在c语言写的 cpython解释器中有这个问题
计算密集型、IO操作
解决:换其他解释器、在需要的位置调用其他语言。
深拷贝、浅拷贝
= 是指向;
copy.copy() 浅拷贝复制引用,不复制数据,节约内存,源数据修改会被影响;
copy.deepcopy() 深拷贝复制数据,不会污染源数据,会占用内存。
列表拷贝,深是深,浅是浅
元组拷贝,两种拷贝都是指向
字典、切片、字符串都是浅拷贝
私有化
作用:数据安全,避免重名
_xxx: 私有属性,防止被导入
__xxx: 私有属性,只在本类中可以用,
__xxx__: 魔法属性, 不能随便定义
xxx__: 避免与关键字冲突
java 语言的私有属性: public int a=5; private String=”aaa”
模块导入
from … import 变量 类似于深拷贝
import 模块 类似于浅拷贝
上一篇: JavaScript基础第四天-02
下一篇: Python学习笔记02-运算符