仿优酷 --- 1

点点圈 提交于 2019-12-03 11:53:19

仿优酷系统第一天总结

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!