11.4总结

一、exec模块

1.是什么?exec 是一个Python内置模块。

2.exec的作用:

'''
x=10
def func():
   pass
'''

可以把“字符串形式”的Python代码,添加到全局或局部名称空间中。

3.怎么用:

参数1:字符串形式的Python代码

参数2:全局名称空间字典

参数3:局部名称空间字典

调用 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)
运行结果:
x=10,....
#添加到局部名称空间
#1.文本形式的Python代码
code='''
x=100
y=200
def func():
   pass
'''
#2.全局的名称空间
global_dict={}
#3.局部的名称空间{}
local_dict={}

exec(code,global_dict,local_dict)
print(local_dict)
运行结果:
{'x': 100, 'y': 200, 'func': <function func at 0x0000000001FF2E18>}

二、元类

1.什么是元类:

元类就是类的类,Chinese类的类是type,type是所有类的类,所以type就是一个元类。

2.元类的作用:

元类可以帮我们控制类的创建

元类可以帮我们控制类的调用

创建类有两种方式:
1.通过class 关键字创建类,内部会自动调用type(),type帮我们创建一个自定义类。
2.通过手动调用type()实例化得到自定义的类。
#1.class创建
'''python中,一切皆对象'''
class Chinese:
    country='China'
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def speak(self):
        print('speak chinese..')

p1=Chinese('tank',18)
print(Chinese)
print(p1)
print(type(p1))
print(type(Chinese))  #type类

#type()-->Chinese--对象
#Chinese()--p1
运行结果:
<class '__main__.Chinese'>
<__main__.Chinese object at 0x000000000284C710>
<class '__main__.Chinese'>
<class 'type'>
#2.type创建:
class_name='Chinese'
class_base=(object, )
class_dict={}
code='''
country="china"
def __init__(self,name,age):
   self.name=name
   self.age=age
def speak(self):
   print("speak chinese..")
'''
exec(code,{},class_dict)
Chinese=type(class_name,class_base,class_dict)
print(Chinese)
运行结果:
<class '__main__.Chinese'>

3.怎么自定义创建元类:

1)自定义一个元类,继承type,派生出自己的属性与方法。

2)给需要使用的类,通过metaclass指定自定义好的元类。

#自定义元类
class MyMeta(type):
    #子类的方法与父类的方法一样,先用子类的,子类覆盖父类的__init__方法。
    #控制子类的定义:
    def __init__(self,class_name,class_base,class_dict):


        #判断字符串首字母是否大写
        if not class_name.istitle():
            raise TypeError('类的首字母必须大写!')

        #控制类中必须要要注释
        if not class_dict.get('__doc__'):
            raise TypeError('类内部必须要写注释!')

        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

# metaclass-->自定义的元类
# 因为Foo类里边什么都不写是默认继承了父类object,因为它继承了元类,所以手动添加它的父类object,什么都不写是默认继承了父类object
class Foo(object,metaclass=MyMeta):
    '''
    这是一个类
    '''
    x=10
    def __init__(self,y,z):
        self.y=y
        self.z=z

    def f1(self):
        print('from Foo.f1..')

foo=Foo(20,30)   #调用Foo对象,会触发__call__

三、ORM:对象关系映射

ORM:映射到数据库MySQL中的数据表

类名-->表名

对象-->一条记录

对象.属性-->字段

模拟Django的ORM,将数据库的增、删、改、查,全部封装成一个个的方式,比如:save,delete,update,select.

#1.创建字段的类型,对应数据表中的一个个字段的创建规范
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 IntegerField(Field):
    def __init__(self,name,column_type='int',primary_key=False,default=0):
        super().__init__(name,column_type,primary_key,default)

class StringField(Field):
    def __init__(self,name,column_type='varchar(64)',primary_key=False,default=None):
        super().__init__(name,column_type,primary_key,default)
# class Father:
#     def __init__(self,*args,**kwargs):
#         self.id=id
#         self.username=args[0]
#         self.password=args[1]
#         self.photo=args[2]

class Models(dict):

    #会在对象.属性没有时触发
    def __getattr__(self, item):
        print(item,'调用没有的属性时会触发..')
        #将字典中key对应的值,返回给对象
        return self.get(item)  #dict_obj.get(key)

    #在对象.属性=值时触发
    def __setattr__(self, key, value):
        print(key,value)
        #给字典对象本身赋值
        self[key]=value

#创建数据表类
#用户表类
class User(Models):
    #强调:最好与字段类型的name属性同名
    user_id=IntegerField(name='user_id')
    user_name=StringField(name='name')
    pwd=StringField(name='pwd')

#电影表类
class Movie(Models):
    pass

user=User(id='007',name='tank',pwd='123')
print(user)
print(type(user))
movie=Movie(m_id='1',m_name='写真集')
print(movie)
print(type(movie))

#字典的取、存值方式
print(user['id'])
user['age']=18
print(user.get('id'))
print(user.get('age'))

user.age=18
print(user.age)

user.sex='male'
print(user.sex)
print(user['sex'])
print(user.__dict__)
运行结果:
{'id': '007', 'name': 'tank', 'pwd': '123'}
<class '__main__.User'>
{'m_id': '1', 'm_name': '写真集'}
<class '__main__.Movie'>
007
007
18
age 18
age 调用没有的属性时会触发..
18
sex male
sex 调用没有的属性时会触发..
male
male
{}
'''
问题1:解决代码冗余问题,比如有100张表,需要写100次__init__
解决1:继承一个父类,父类中定义一个__init__

问题2:无法预测每一张表中的字段是什么,无法通过父类的__init__ 解决问题
解决2:通过继承字典,内部的__init__,可以接受‘任意个数’的‘关键字参数’

问题3:继承字典的类实例化的对象,无法通过‘对象.属性的方式存取值
解决3:通过__setatter__,__getattr__来实现,让字典对象与普通对象一模一样,并且具备字典原有的特性
'''

猜你喜欢

转载自www.cnblogs.com/lidandanaa/p/11795595.html