仿优酷系统第一天总结
exec
exec是python解释器中的一个函数,使用方法与正常函数的使用方法是一样的
exec中有三个参数
1.包含python代码的字符串
2.全局作用域(字典形式),如果不指定,默认是globals()
3.局部作用域(字典行式),如果不指定,默认是locals()
将exec命令的执行当作是一个函数的执行,会将执行期间产生的名字存放于局部名称空间中。
例:
# 全局名称空间
# # 1.文本形式的python代码
code = '''
global x
x = 10
y = 20
'''
# 2.全名的名称空间 {}
global_dict = {'x': 200}
# 3.局部名称空间 {}
local_dict = {}
exec(code, global_dict, local_dict)
print(global_dict)
# 局部名称空间
# 1.文本形式的python代码
code = '''
x = 100
y = 200
def func():
pass
'''
# 2.全名的名称空间 {}
global_dict = {}
# 3.局部名称空间 {}
local_dict = {}
exec(code, global_dict, local_dict)
# print(global_dict)
print(local_dict)
元类
1.什么是元类
元类就是类的类,type是所有类的类,type就是一个元类
2.元类的作用
元类可以帮助我们控制类的创建
2.如何自定义创建元类
1.自定义一个元类,继承type,派生出自己的属性与方法
2.给需要使用的类,通过metaclass指定自定义好的元类
例:
# 自定义元类
class MyMeta(type):
# 子类的方法与父类的方法一样,先用子类的,子类覆盖父类的__init__方法。
# 控制了类的定义
def __init__(self, class_name, class_base, class_dict):
# print(class_name)
# 判断字符串首字母是否大写
if not class_name.istitle():
raise TypeError('类的首字母必须大写!')
# 控制类中必须要有注释
if not class_dict.get('__doc__'):
raise TypeError('类内部必须要写注释!')
# print(class_base)
# print(class_dict)
super().__init__(class_name, class_base, class_dict)
# 模拟type元类内部做的事情
# 元类触发的__call__可以控制类的调用。调用__call__会触发以下两点
def __call__(self, *args, **kwargs):
# 1.会调用__new__()--> obj, 会创建一个空对象。
obj = object.__new__(self)
# 2.会执行__init__(obj, *args, **kwargs),
obj.__init__(*args, **kwargs)
return obj
# 可以通过元类内部的__new__控制对象的创建
def __new__(cls, *args, **kwargs):
pass
class Bar:
pass
# metaclass ---> 自定义的元类
# 因为Foo类继承了元类,必须手动继承object
class Foo(Bar, metaclass=MyMeta): # MyMeta(Foo, Foo_name, (Bar, ), foo_dict)
'''
这是一个Foo类
'''
# 摊开坦克
x = 10
def __init__(self, y, z):
self.y = y
self.z = z
def f1(self):
print('from Foo.f1...')
仿优酷系统总结
1.仿优酷的架构
---用户视图层
---接口层
---数据层(主要)
2.数据库存储数据的格式最好是使用josn串的格式,因为json可以实现跨平台交互。保存的时候按照字典的格式来保存是因为可以利用字典的方便存取,可以通过键值对的方式进行存取。
3.数据库中的字段是有格式的,在创建字段的时候,分别是字段名 列类型 [可选参数] 约束条件,将每个字段都写成对象的格式,这样在判断字段的时候可以直接通过对象.属性的方式来进行取值,对字段进行判断。
4.在存储以及写入数据的时候都按照对象.方法的方式来进行存取,这样比较方便进行操作
5.类名.__dict可以查看类的名称空间内的所有名称,
raise TypeError('必须有一个主键') 可以返回错误
items() 会将字典中的每一项以列表的行式返回,列表中的每一项都是以键值对的行式表现
字典名.key() 遍历字典中的所有key
dict也是一个类,可以继承字典,当父类继承字典的时候,可以自由输入值,不受约束,输入的值的格式必须是键值对格式。
6.以下是今天将的ORM的一些代码
# 现在写的是数据库的表字段格式,如何去创建一个表,模仿数据库去创建一个表,表有字典,列类型,约束条件
# 先写字典字段名的列类型(字段名,数据类型,约束条件,主键,默认值)
# 通过数字型和字符串类型进行抽象,找到公共部分写出来父类
class Field:
def __init__(self, name, column_type, primary_key, default):
self.name = name
self.column_type = column_type
self.primary_key = primary_key
self.default = default
# 数字型
class Int(Field):
def __init__(self,name,column_type='int',primary_key=False,default=0):
super().__init__(name,column_type,primary_key,default)
# 字符串类型
class Str(Field):
def __init__(self, name, column_type='varchar(64)', primary_key=False, default=None):
super().__init__(name,column_type,primary_key,default)
'''
关于字段的数据类型已经创建完成,之后在使用的时候,
直接讲需要的类型参数传进去,就可以创建出自己需要的字段类型
'''
'''
关于表的问题:有一个数据库中有用户的表,也有存放电影的表
表的特征:
1.表名只能有一个,
2.给表强加属性,主键只能有一个,必须是唯一的
3.将数据表中所有的字段对象都存放在一个独立的字典中,目的是为了方便存取
问题1:解决代码冗余的问题,如果有一百张表,怎么办
问题2:无法预测每张表中的字段是什么,无法通过父类的__init__解决问题
问题3:继承字典的类实例化的对象,无法通过“对象.属性”的方式存取值
'''
# 写一个元类
class OrmMetaClass(type):
def __new__(cls,class_name,class_base,class_dict):
# class_name 类名---》表名
# class_base 基类/父类
# class_dict 类的名称空间
if class_name == 'Models':
return type.__new__(cls,class_name,class_base,class_dict)
# 1.一张表必须要有表名
table_name = class_dict.get('table_name',class_name)
#2.主键名
primary_key = None
# 3.定义一个空字典,专门用来存放字段对象
mappings = {}
for key,value in class_dict.items(): # items会讲字典中的每一项以列表的行式返回,列表中的每一项都是以键值对的行式表现
# 现在拿到的键值对是名称空间中的键值对
if isinstance(value,Field):
mappings[key] = value
# 判断字段对象是否是主键
if value.primary_key:
# 嫌犯段初始的primary_key是否为True
# 判断主键是否已经存在
if primary_key:
raise TypeError('只能由一个主键')
# 若主键不存在,则给primari__key赋值
primary_key = value.name
# 节省资源:因为mappings与元类中名称空间中的属性重复,为了节省内存,提出重复的属性
for key in mappings.key(): # 遍历字典中的key
class_dict.pop(key) # pop函数用于移除列表中的元素
# 判断是否有主见
if not primary_key:
raise TypeError('必须有一个主键')
# 给类的名称空间添加表名
class_dict['table_name'] = table_name
# 给类的名称空间添加主键名
class_dict['primary_key'] = primary_key
# 给类的名称空间添加一个mappings字典,字典中拥有所有字段属性
class_dict['mappings'] = mappings
return type.__new__(cls,class_name,class_base,class_dict)
# 根据用户表与电影表信息创建一个父类
class Models(dict):
def __getattr__(self, item):
print(item,'对象.属性没有的时候触发')
return self.get(item)
# 给对象添加属性的时候触发,对象.属性=值
def __setattr__(self, key, value):
self[key] = value
# 先建立用户表
class User(Models,metaclass=OrmMetaClass):
user_id = Int(name='user_id',primary_key=True)
user_name = Str(name='name')
pwd = Str(name='pwd')
'''
当父类继承字典的时候,这种写法,可以自由输入值,不受约束,输入的值的格式必须是键值对的格式
'''
# 视频表
class Movies:
def __init__(self,movies_id,movies_name,movies_string):
pass