python基础
meta编程(元编程)
元编程指编写代码的代码
python中,元编程是指一种构建函数和类的行为,这些函数和类可以通过修改、包装现有代码或生成代码来进行操纵。实现方法是装饰器或者元类(type)
- 装饰器(不赘述)
def descr(func):
@wraps(func)
def inner(*args, **kwargs):
print("descr after")
req = func(*args, **kwargs)
print("descr before")
return req
return inner
- 元编程
"python中,type生class,class生万物,type则自己生自己"
>>> class Foo:
... pass
...
>>> type(Foo)
<class 'type'>
>>> f = Foo()
>>> type(f)
<class '__main__.Foo'>
>>> type(type)
<class 'type'>
上面代码显示了类实例,类和type的关系。也可以用.__class__来追溯这一过程。
下面用type来创造一个类
>>>class_example = type('class_example', (), {}) # 三个参数分别是类名字,继承的父类和类属性*(方法,属性等)
>>>print(class_example)
<class '__main__.class_example'>
同理python使用中经常用到的hasattr和setattr可查询和添加类属性(方法,属性)
>>> f.attr1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'attr1'
>>> setattr(Foo,"attr1","reslut attr1")
>>> f.attr1
'reslut attr1'
- metaclass
整个元编程上面都说完了,只是用起来没那么简洁或者没那么oop。metaclass就是生成类的方法(函数)
def my_meta(classname, father_class, attr):
return type(classname, father_class, attr)
class Foo:
__metaclass__ = my_meta
上面代码看得出,在创建class的时候python是去找的__metaclass__方法,要是没找到就直接用type,这里我们自定义了一个__metaclass_。(另外子类不继承父类的__metaclass__更深层次的看参考文章1)
应用实例:
django的model.Model。在orm(特指django的orm)中所有class都继承了model.Model在Ctrl点击进去看看就明白了
class Classes(models.Model):
name = models.CharField(max_length=32)
institude = models.CharField(max_length=32)
headteacher = models.ForeignKey("Teacher")
Ctrl点进去models.Model
class Model(metaclass=ModelBase): # == __meaclass__ 通过继承的方式显的更oop一些嘛
......
Ctrl点进去ModelBase
class ModelBase(type): # 这里继承type也证明了一切都是type来的,包括你__metalclass__
"""Metaclass for all models."""
def __new__(cls, name, bases, attrs, **kwargs):
super_new = super().__new__
......
通过这种继承Model,Model再里面进行操作,最终导致我们在调用orm对象(一个实例)的属性(.age .name)的时候直接返回的是具体的数字或者字符串而不是IntegerField或者CharField的对象。
忽悠:元编程就是编写代码的代码,python中都知道万物皆对象,对象由类通过new生成,new调用init初始化内存生成实例。那类就是由metaclass调用type生成的。type就是元编程的方式之一。可以通过调用type和三个参数直接生成一个类;也可以在类中添加__metaclass__自定义方法最后return一个type,其实还是type。也可以通过setattr来修改类。广义上讲装饰器也是元编程,它也修改了函数这个对象的代码,所以叫编写代码的代码。比如django的model就是这么实现。装逼的说说......
参考链接:
https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python/6581949#6581949
https://blog.csdn.net/cdlwhm1217096231
- python2和3的区别
语法上:print input
编码上:python3默认使用utf-8
迭代器:生成列表range
模块上:注意模块使用的不同 - 生成器和迭代器
迭代器是指实现iter和next方法的就是迭代器,生成器是延伸出来的通过yeild实现。 - 深拷贝
from copy import deepcopy
a = [1,2,3,[4,5]]
b=a
c = deepcopy(a) // 深拷贝,copy.copy是浅拷贝。第一层相互不影响,内层影响
a.append(6)
b.append(7)
a[3].append(11)
print(a)
print(b)
print(c)
- map,filter,reduce
map:将一个列表(可迭代类型)每个元素带入到一个函数中 a = list(map(lambda x:x*x,[1,2,3])) 结果是 [1,4,9]
filter:同理过滤一个列表 a = list(filter(lambda x:x%2==1, [1,2,3,4,5])) 结果是[1,3,5]
reduce:将列表前后迭代入函数 a = reduce(lambda x, y: x + y, [1,2,3,4]) 结果是1+2+3+4=10 - 多肽
python面向对象的三个特征:封装,继承,多肽
封装:使用构造方法将内容封装到对象中
继承:继承父类,python3新式类的c3算法。 - 字典的排序
一种方法,多了不记,恶心蛋疼。
sorted(dict.items(), lambda x:x[0]) # 0表示key排序 1表示值排序 reverse参数 - 正则匹配中search和match
match是开头匹配。search是在字符串中,并且match返回<re.Match object; span=(0, 5), match='https'> span表示从哪里匹配到的。search的方法是.group 返回匹配的数据。.groups返回一个列表里面是匹配在括号的内容。
框架(django主)相关
-
orm查询
字段设置:
V=models.CharField(max_length=None<, options>) #varchar
V=models.EmailField(<max_length=75, options="">) #varchar
V=models.URLField(<verify_exists=true, options="" max_length="200,">) #varchar
V=models.FileField(upload_to=None<, max_length=100, options>) #varchar #upload_to指定保存目录可带格式,
V=models.ImageField(upload_to=None<, height_field=None, width_field=None, max_length=100, options>)
V=models.IPAddressField(<options>) #varchar
V=models.FilePathField(path=None<, match=None, recursive=False, max_length=100, options>) #varchar
V=models.SlugField(<max_length=50, options="">) #varchar,标签,内含索引
V=models.CommaSeparatedIntegerField(max_length=None<, options>) #varchar
V=models.IntegerField(<options>) #int
V=models.PositiveIntegerField(<options>) #int 正整数
V=models.SmallIntegerField(<options>) #smallint
V=models.PositiveSmallIntegerField(<options>) #smallint 正整数
V=models.AutoField(options) #int;在Django代码内是自增
V=models.DecimalField(max_digits=None, decimal_places=None<, options>) #decimal
V=models.FloatField(<options>) #real V=models.BooleanField(options) #boolean或bit
V=models.NullBooleanField(<options>) #bit字段上可以设置上null值
V=models.DateField(<auto_now=false, **options="" auto_now_add="False,">) #date #auto_now最后修改记录的日期;auto_now_add添加记录的日期
V=models.DateTimeField(<auto_now=false, **options="" auto_now_add="False,">) #datetime
V=models.TimeField(<auto_now=false, options="" auto_now_add="False,">) #time
V=models.TextField(<options>) #text
V=models.XMLField(schema_path=None<, **options>) #text ——————————————————————————–
V=models.ForeignKey(othermodel<, **options>) #外键,关联其它模型,创建关联索引
V=models.ManyToManyField(othermodel<, **options>) #多对多,关联其它模型,创建关联表
V=models.OneToOneField(othermodel<, parent_link=False, **options>) #一对一,字段关联表属性
字段参数设置:
null 数据库中字段是否可以为空
db_column 数据库中字段的列名
default 数据库中字段的默认值
primary_key 数据库中字段是否为主键
db_index 数据库中字段是否可以建立索引
unique 数据库中字段是否可以建立唯一索引
unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引
unique_for_month 数据库中字段【月】部分是否可以建立唯一索引
unique_for_year 数据库中字段【年】部分是否可以建立唯一索引
verbose_name Admin中显示的字段名称
blank Admin中是否允许用户输入为空
editable Admin中是否可以编辑
help_text Admin中该字段的提示信息
choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)
error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息;
字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
如:{'null': "不能为空.", 'invalid': '格式错误'}
validators 自定义错误验证(列表类型),从而定制想要的验证规则
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator,URLValidator,DecimalValidator,
MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
如:
test = models.CharField(
max_length=32,
error_messages={
'c1': '优先错信息1',
'c2': '优先错信息2',
'c3': '优先错信息3',
},
validators=[
RegexValidator(regex='root_d+', message='错误了', code='c1'),
RegexValidator(regex='root_112233d+', message='又错误了', code='c2'),
EmailValidator(message='又错误了', code='c3'), ]
)
元信息:
class UserInfo(models.Model):
nid = models.AutoField(primary_key=True)
username = models.CharField(max_length=32)
class Meta:
# 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
db_table = "table_name"
# 联合索引
index_together = [
("pub_date", "deadline"),
]
# 联合唯一索引
unique_together = (("driver", "restaurant"),)
# admin中显示的表名称
verbose_name
# verbose_name加s
verbose_name_plural
多对多参数:
ForeignKey(ForeignObject) # ForeignObject(RelatedField)
to, # 要进行关联的表名
to_field=None, # 要关联的表中的字段名称
on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为
- models.CASCADE,删除关联数据,与之关联也删除
- models.DO_NOTHING,删除关联数据,引发错误IntegrityError
- models.PROTECT,删除关联数据,引发错误ProtectedError
- models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
- models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
- models.SET,删除关联数据,
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)def func(): return 10 class MyModel(models.Model): user = models.ForeignKey( to="User", to_field="id" on_delete=models.SET(func),) related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all() related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名') limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件: # 如: - limit_choices_to={'nid__gt': 5} - limit_choices_to=lambda : {'nid__gt': 5} from django.db.models import Q - limit_choices_to=Q(nid__gt=10) - limit_choices_to=Q(nid=8) | Q(nid__gt=10) - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') db_constraint=True # 是否在数据库中创建外键约束 parent_link=False # 在Admin中是否显示关联数据
OneToOneField(ForeignKey)
to, # 要进行关联的表名
to_field=None # 要关联的表中的字段名称
on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为###### 对于一对一 ###### # 1. 一对一其实就是 一对多 + 唯一索引 # 2.当两个类之间有继承关系时,默认会创建一个一对一字段 # 如下会在A表中额外增加一个c_ptr_id列且唯一: class C(models.Model): nid = models.AutoField(primary_key=True) part = models.CharField(max_length=12) class A(C): id = models.AutoField(primary_key=True) code = models.CharField(max_length=1)
ManyToManyField(RelatedField)
to, # 要进行关联的表名
related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件:
# 如:
- limit_choices_to={'nid__gt': 5}
- limit_choices_to=lambda : {'nid__gt': 5}from django.db.models import Q - limit_choices_to=Q(nid__gt=10) - limit_choices_to=Q(nid=8) | Q(nid__gt=10) - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') symmetrical=None, # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段 # 做如下操作时,不同的symmetrical会有不同的可选字段 models.BB.objects.filter(...) # 可选字段有:code, id, m1 class BB(models.Model): code = models.CharField(max_length=12) m1 = models.ManyToManyField('self',symmetrical=True) # 可选字段有: bb, code, id, m1 class BB(models.Model): code = models.CharField(max_length=12) m1 = models.ManyToManyField('self',symmetrical=False) through=None, # 自定义第三张表时,使用字段用于指定关系表 through_fields=None, # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表 from django.db import models class Person(models.Model): name = models.CharField(max_length=50) class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField( Person, through='Membership', through_fields=('group', 'person'), ) class Membership(models.Model): group = models.ForeignKey(Group, on_delete=models.CASCADE) person = models.ForeignKey(Person, on_delete=models.CASCADE) inviter = models.ForeignKey( Person, on_delete=models.CASCADE, related_name="membership_invites", ) invite_reason = models.CharField(max_length=64) db_constraint=True, # 是否在数据库中创建外键约束 db_table=None, # 默认创建第三张表时,数据库中表的名称
查询参数:
# 大于,小于
#
# models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值
# models.Tb1.objects.filter(id__gte=1) # 获取id大于等于1的值
# models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值
# models.Tb1.objects.filter(id__lte=10) # 获取id小于10的值
# models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值
# in
#
# models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
# models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in
# order by
#
# models.Tb1.objects.filter(name='seven').order_by('id') # asc
# models.Tb1.objects.filter(name='seven').order_by('-id') # desc
# group by
#
# from django.db.models import Count, Min, Max, Sum
# models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
# SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE
"app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
# limit 、offset
#
# models.Tb1.objects.all()[10:20]
外键查询:
A表中ForeignKeyB(字段名b),A中有B
A.b 正常通过点来获取
A.objects.filter(b__id=0) 链式查询
B.A_set 反向查
-
懒加载机制
queryset默认施行懒加载,在.all()的queryset对象中,_result_cache用来缓存查询结果,只有在print或者list真正使用时候才在_result_cache中有数据。同理这种做法缺点也有容易多次重复查询。解决办法是:select_raleted和prefetch_raleted方法。前者是针对一对一和一对多,后者则是针对多对多或者方向一对多。两者都是一次讲关联数据查询到,防止重复查询。 -
asgi
同 WSGI 一样,Django 也支持使用 ASGI 来部署,它是为了支持异步网络服务器和应用而新出现的 Python 标准。--来自django文档 -
接口限流
django throttle(基于登录未登录次数和频率) -
事务装饰器
@transaction.atomic
def view(req):
try:
...
save1 = transaction.savepoint()
with tansaction.atomic():
...
except:
transaction.savepoint_rollback(save1) # 回滚到保存点
transaction.savepoint_commit(save1) # 提交从保存点到当前状态的所有数据库事务操作 -
tornado异步调用同步
文档推荐@run_on_exector(装饰器)调用同步函数。如若堵死,用concurrent开启多线程。
数据库相关(mysql主) -
聚簇原则
innodb的b+tree主键和数据行data都在一个子叶上,找到主键就找到了数据行。二级索引保存的是主键值,二级索引至少要两次查询才能找到数据行 -
cache机制(未命中走那两层)
首先mysql的缓存机制是:
当命中缓存是,会跳过sql解析,优化,生成计划阶段返回数据。而要命中缓存对sql要求很高,不能包含不确定sql语句(NOW(),CURRENT_DATE(),自定义函数,用户变量,有列权限的表等),且空格,注释的不同也不会命中。一旦涉及到的表或者数据库改变则缓存失效。
缓存优点和缺点:查询很快,因为缓存存在内存中。缺点是每次的写操作会带来额外的失效缓存的时间;每次生成缓存排它锁一下;一旦某个大表缓存碎片很多,经历过一次修改后,造成雪崩。所以根据优缺点去设置表的缓存。
mysql就连接层,sql服务层,引擎层和存储层,还搁那里两层。面试的人一般都要显示自己的牛逼。 -
b+tree能存多少数据,计算方式
假设一个页数据默认16KB,主键一般占用4B,外加其他数据假如是12B。那一个页就有1k(1024)个主键,三阶就能存10**3乘三次就是10亿数据。 -
redis哪些数据结构和语法
字符串类型:get,set,mset,mget,setbite
hash类型:hget,hset,hmset,hgetall
list:lpop,lpush,lindex -
关系型和非关系型数据库的区别
结构上:关系型数据结构固定;非关系型离散,k-v对,文档类型。MongoDB字段和表都是随意添加。
扩展性:关系型横向拓展不容易
数据一致性:关系型对ACID要求严格 -
为什么使用monggodb,为什么使用mysql
MongoDB新增数据或者增加字段非常容易,mysql则是我们结构性字段,一般不修改。修改就是大修改。
算法
匹配一个IP地址
import re
#简单的匹配给定的字符串是否是ip地址,下面的例子它不是IPv4的地址,但是它满足正则表达式
if re.match(r"^(?:[0-9]{1,3}.){3}[0-9]{1,3}$", "272.168,1,1"):
print "IP vaild"
else:
print "IP invaild"
#精确的匹配给定的字符串是否是IP地址
if re.match(r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", "223.168.1.1"):
print "IP vaild"
else:
print "IP invaild"
#简单的从长文本中提取中提取ip地址
string_ip = "is this 289.22.22.22 ip ?
result = re.findall(r"(?:[0-9]{1,3}.){3}[0-9]{1,3}", string_ip)
if result:
print result
else:
print "re cannot find ip"
#精确提取IP
result = re.findall(r"(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)", string_ip):
if result:
print result
else:
print "re cannot find ip
- 冒泡,归并和快速
# 冒泡 先排最大的 所以第二循环去除最后len(arr) - 1
# def bubbleSort(arr):
# g = 0
# for i in range(1, len(arr)):
# for j in range(0, len(arr)-i):
# g += 1
# if arr[j] > arr[j+1]:
# arr[j], arr[j + 1] = arr[j + 1], arr[j]
# print(arr)
# print(g)
# return arr
# bubbleSort(a)
# 归并 无限分成两段 默认每段都是有序的 俩俩比对
# def merge(l, r):
# req = []
#
# while l and r:
# if l[0] < r[0]:
# req.append(l.pop(0))
# else:
# req.append(r.pop(0))
#
# if l:
# for i in l:
# req.append(i)
# if r:
# for i in r:
# req.append(i)
# return req
#
# def merge_s(a):
# if len(a) < 2:
# return a
# mid = round(len(a)/2)
# l = a[0:mid]
# r = a[mid:]
# return merge(merge_s(l), merge_s(r))
#
# print(merge_s(a))
#
# 快速排序
# def quicksort(arr):
# if len(arr) <= 1:
# return arr
# pivot = arr[round(len(arr) / 2)]
# left = [x for x in arr if x < pivot]
# middle = [x for x in arr if x == pivot]
# right = [x for x in arr if x > pivot]
# return quicksort(left) + middle + quicksort(right)
网络和web
- tcp/ip五层结构
应用层:应用程序和他们的协议存放的地方。HTTP,SMTP,FTP
运输层:运送应用程序端点之间传送应用层报文。TCP,UDP
网络层:负责主机间的数据交互 IP
链路层:负责路由数据报文
物理层:负责更进一步 - 上下文管理器如何切换
1挂起被中断的进程或者线程(系统中断,用户yeild)2 讲挂起的进程信息(堆栈,指令行)保存到cpu的一个内存中(PCB) 3cpu寄存器加载下个进程在PCB的信息 4在被中断的位置找到指令行执行 - 内核态和用户态
系统执行进程的两种状态。区别在于权力的大小:内核态是cpu ring0级用户态是ring4级别,内核态可以调配系统资源(cpu,内存,文件和网络等)而限制用户态的权力。用户态用过系统调用转为内核态