python 异步io并发_Python高级编程和异步IO并发编程(笔记)

一、魔法函数

#例子

classCompany(object):def __init__(self, employee_list):

self.employee=employee_listdef __getitem__(self, item):returnself.employee[item]def __len__(self):returnlen(self.employee)

company= Company(["tom", "bob", "jane"])

1、在类中实现了__getitem__方法,就可以对类Company的实例进行切片,遍历的操作------>for循环调用__iter__方法,如果没有就调用__getitem__方法,其中的参数item是Python解释器会帮我们填进去的(从0开始),直到报错了for循环才停止。

2、用len()来读取Python的内置类型例如list,dict,set的效率很高,因为此时Python不会去遍历,而是会直接读取list的长度

对魔法函数的总结:Python语法会识别魔法函数,对其的调用是隐射的。可以把魔法函数看成是独立的存在,而不是对谁的调用或者从object继承。往类里面加入魔法函数后,会增强我们类的类型,例如类可以进行切片操作了,相当于把类变成了序列类型

二、深入类和对象

1、动态语言与鸭子类型

动态语言中经常提到鸭子类型,所谓鸭子类型就是:如果走起路来像鸭子,叫起来也像鸭子,那么它就是鸭子(If it walks like a duck and quacks like a duck, it must be a duck)。鸭子类型是编程语言中动态类型语言中的一种设计风格,一个对象的特征不是由父类决定,而是通过对象的方法决定的。

静态语言中对象的特性取决于其父类。而动态语言则不一样,比如迭代器,任何实现了 __iter__ 和 __next__方法的对象都可称之为迭代器,但对象本身是什么类型不受限制,可以自定义为任何类。

#isinstance 和·type的区别

classA(object):pass

classB(A):passb=B()

type(b)is B -------->True

type(b)is A -------->False

type(b)是指向B这个全局唯一的类的

2、类属性的查找顺序

#深度优先算法对于菱形继承的情况有问题---->例如A是B和C的父类,D同时继承B和C,若方法func在A中存在,在C中被重新定义,若采用深度优先算法,D.func调用的是A中的func,而不是C中重写的func#广度优先算法对于重名问题有问题----->例如D同时继承B和C,A是B的父类,若想通过D.func调用A中的func,但因为如果C中刚好也有重名方法func的话,将导致被覆盖#C3算法(MRO算法)---》根据继承内容选择是深度优先还是广度优先

#super不是调用父类,而是调用MRO里面顺序的类

#类的多继承问题的解决方法--->参考mixin的设计思路#mixin模式特点#1. Mixin类功能单一#2. 不和基类关联,可以和任意基类组合, 基类可以不和mixin关联就能初始化成功#3. 在mixin中不要使用super这种用法

#要修改类方法,通过 类名.xxx 调用,不能通过实例调用赋值#dir() 查找对象的属性,比__dict__强大

3、Python是基于协议进行编程的

上下文管理协议

(1)

#try:

print("...")raiseKeyerror#except Keyerror:

return 1

#else:

...#finally:

return 2

#注意返回的是2不是1,1和2都被压栈,但只弹出顶层的元素

(2)__enter__和__exit__

写try...finally非常繁琐。Python的with语句允许我们非常方便地使用资源,而不必担心资源没有关闭。

实际上,任何对象,只要正确实现了上下文管理,就可以用于with语句。

实现上下文管理是通过__enter__和__exit__这两个方法实现的。

#上下文管理器协议

classSample:def __enter__(self):print ("enter")#获取资源

returnselfdef __exit__(self, exc_type, exc_val, exc_tb):#释放资源

print ("exit")defdo_something(self):print ("doing something")

with Sample() as sample:

sample.do_something()

(3)@contextlib.contextmanager

编写__enter__和__exit__仍然很繁琐,因此Python的标准库contextlib提供了更简单的写法,上面的代码可以改写如下:

importcontextlib

@contextlib.contextmanagerdeffile_open(file_name):print ("file open")yield{}print ("file end")

with file_open("bobby.txt") as f_opened:print ("file processing")

三、自定义序列类

#+、+=、extend的区别#+ 的本质是重新创建一个新的列表,地址改变#+= 的内部实现一个__iadd__的魔法函数,里面调用extend(),在内部进行for循环append进去,所以只要接受一个可迭代的类型就行,而+必须跟同类型的。在a的基础上进行修改,地址不变#append 直接把数组当成一个值传进去#+= ----> extend -----> append

#列表推导式,如果只有一个if,就把if放在for后面,如果有if else,就放在for前面

from collections.abc importMutableMapping

a={}

isinstance(a, MutableMapping)#--------> True 不是a继承了MutableMapping,而是a这个字典实现了MutableMapping里面的部分魔法函数,源码里面是把{}注册到MutableMapping中

四、深入理解dict和set

#dict查找的性能远大于list#在list中随着list数据的增大 查找时间会增大#在dict中查找元素不会随着dict的增大而增大

#dict的内部实现是通过哈希表(set也是)#dict为什么查找那么快?---->利用数组,通过偏移量直接找到数据,时间复杂度是O(1),而且不会随着数据量的增大而使查找速度下降#所以key必须可哈希--->不可变对象都是可哈希#dict的内存花销大(hash的缺点,一开始会申请比较大的内存空间,降低冲突的机会),但是查询速度快, 自定义的对象 或者python内部的对象都是用dict包装的#dict的存储顺序和元素添加顺序有关---->因为可能会冲突,先储存,就先占据某个位置#添加数据有可能改变已有数据的顺序--->因为当数据过多,重新开始申请一块更大的内存,把数据搬迁过去的时候,会改变存储顺序

五、对象引用、可变性和垃圾回收

#python和java(变量相当于一个盒子)中的变量本质不一样,python的变量实质上是一个指针 int str, 便利贴#变量大小是固定的

a = 1a= "abc"

#1. a贴在1上面#2. 先生成对象 然后贴便利贴#cpython中垃圾回收的算法是采用 引用计数

一个经典错误

classCompany:def __init__(self, name, staffs=[]):

self.name=name

self.staffs=staffsdefadd(self, staff_name):

self.staffs.append(staff_name)defremove(self, staff_name):

self.staffs.remove(staff_name)if __name__ == "__main__":

com1= Company("com1", ["bobby1", "bobby2"])

com1.add("bobby3")

com1.remove("bobby1")print(com1.staffs)

com2= Company("com2")

com2.add("bobby")print(com2.staffs) # [bobby]print (Company.__init__.__defaults__)

com3= Company("com3")

com3.add("bobby5")print(com2.staffs) # [bobby, bobby5]print(com3.staffs) # [bobby, bobby5]print (com2.staffs iscom3.staffs) # True#因为com2和com3公用一个默认变量

六、元类编程

(1) property动态属性

from datetime importdate, datetimeclassUser:def __init__(self, name, birthday):

self.name=name

self.birthday=birthday

self._age=0#def get_age(self):

#return datetime.now().year - self.birthday.year

@propertydefage(self):return datetime.now().year -self.birthday.year

@age.setterdefage(self, value):

self._age=valueif __name__ == "__main__":

user= User("bobby", date(year=1987, month=1, day=1))

user.age= 30

print(user._age)print(user.age)

(2)数据描述符和非数据描述符

classIntField:#数据描述符

def __get__(self, instance, owner):returnself.valuedef __set__(self, instance, value):if notisinstance(value, numbers.Integral):raise ValueError("int value need")if value <0:raise ValueError("positive value need")

self.value=valuedef __delete__(self, instance):pass

classNonDataIntField:#非数据属性描述符

def __get__(self, instance, owner):returnself.valueclassUser:

age=IntField()#age = NonDataIntField()

'''如果user是某个类的实例,那么user.age(以及等价的getattr(user,’age’))

首先调用__getattribute__。如果类定义了__getattr__方法,

那么在__getattribute__抛出 AttributeError 的时候就会调用到__getattr__,

而对于描述符(__get__)的调用,则是发生在__getattribute__内部的。

user = User(), 那么user.age 顺序如下:

(1)如果“age”是出现在User或其基类的__dict__中, 且age是data descriptor(数据描述符), 那么调用其__get__方法, 否则

(2)如果“age”出现在user的__dict__中, 那么直接返回 obj.__dict__[‘age’], 否则

(3)如果“age”出现在User或其基类的__dict__中

(3.1)如果age是non-data descriptor,那么调用其__get__方法, 否则

(3.2)返回 __dict__[‘age’]

(4)如果User有__getattr__方法,调用__getattr__方法,否则

(5)抛出AttributeError'''

(3)ORM的实现

classField:pass

classIntField(Field):#数据描述符

def __init__(self, db_column, min_value=None, max_value=None):

self._value=None

self.min_value=min_value

self.max_value=max_value

self.db_column=db_columnif min_value is notNone:if notisinstance(min_value, numbers.Integral):raise ValueError("min_value must be int")elif min_value <0:raise ValueError("min_value must be positive int")if max_value is notNone:if notisinstance(max_value, numbers.Integral):raise ValueError("max_value must be int")elif max_value <0:raise ValueError("max_value must be positive int")if min_value is not None and max_value is notNone:if min_value >max_value:raise ValueError("min_value must be smaller than max_value")def __get__(self, instance, owner):returnself._valuedef __set__(self, instance, value):if notisinstance(value, numbers.Integral):raise ValueError("int value need")if value < self.min_value or value >self.max_value:raise ValueError("value must between min_value and max_value")

self._value=valueclassCharField(Field):def __init__(self, db_column, max_length=None):

self._value=None

self.db_column=db_columnif max_length isNone:raise ValueError("you must spcify max_lenth for charfiled")

self.max_length=max_lengthdef __get__(self, instance, owner):returnself._valuedef __set__(self, instance, value):if notisinstance(value, str):raise ValueError("string value need")if len(value) >self.max_length:raise ValueError("value len excess len of max_length")

self._value=valueclassModelMetaClass(type):def __new__(cls, name, bases, attrs, **kwargs):if name == "BaseModel": #不是BaseModel才是我们定义的User,才需要进行一系列处理

return super().__new__(cls, name, bases, attrs, **kwargs)

fields={}for key, value inattrs.items():if isinstance(value, Field): #因为可能是IntField或者CharField,或者判断是否是Field

fields[key] =value

attrs_meta= attrs.get("Meta", None)

_meta={}

db_table=name.lower()if attrs_meta is notNone:

table= getattr(attrs_meta, "db_table", None)if table is notNone:

db_table=table

_meta["db_table"] =db_table

attrs["_meta"] =_meta

attrs["fields"] =fieldsdel attrs["Meta"] #去掉不需要的Meta,已经有_meta了

#上面这几步相当于对attrs进行处理,最后在一起委托给父类new方法

return super().__new__(cls, name, bases, attrs, **kwargs)class BaseModel(metaclass=ModelMetaClass):def __init__(self, *args, **kwargs):for key, value inkwargs.items():

setattr(self, key, value)return super().__init__()defsave(self):

fields=[]

values=[]for key, value inself.fields.items():

db_column=value.db_columnif db_column isNone:

db_column=key.lower()

fields.append(db_column)

value=getattr(self, key)

values.append(str(value))#需要把字符串类型的value用单引号包起来(未处理)

sql = "insert {db_table}({fields}) value({values})".format(db_table=self._meta["db_table"],fields=",".join(fields), values=",".join(values))pass

classUser(BaseModel):

name= CharField(db_column="name", max_length=10)

age= IntField(db_column="age", min_value=1, max_value=100)classMeta:

db_table= "user"

if __name__ == "__main__":

user= User(name="bobby", age=28)#user.name = "bobby"

#user.age = 28

user.save()

View Code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值