exec模块、元类、python连接数据库
今日学习总结:
一、exec模块:是一个python内置的函数,可以将字符串的代码添加到名称空间中
语法:exec(字符串形式的代码,全局名称空间,局部名称空间)
code =''' x=10 y=20 def func(): pass ''' #自定义一个全局名称空间 global_dic={ 'x':10000 } print(global_dic) #自定义一个局部名称空间 local_dic={ 'y':200 } print(local_dic) exec(code,global_dic,local_dic) print(global_dic) # 结果有x=10000,还有其他 print(local_dic) # 结果是 code里面的东西:因为exec, code相当于局部名称空间中的名字 # {'y': 20, 'x': 10, 'func': <function func at 0x00000000004F2E18>} # class Foo: # # pass # print(Foo.__dict__) #__dict__表示 名称空间,是一个字典
code是局部名称空间,在code 中声明全局变量。
code =''' global x # 这里把x设成了全局变量,所以局部的名称空间里没有了x,全局名称空间里x的值变了 x=10 y=20 def func(): pass ''' #自定义一个全局名称空间 global_dic={ 'x':10000 } print(global_dic) #自定义一个局部名称空间 local_dic={ 'y':200 } print(local_dic) exec(code,global_dic,local_dic) print(global_dic) # 结果有x=10,还有其他 print(local_dic) # 结果是 code里面的东西 # {'y': 20,'func': <function func at 0x00000000004F2E18>}
二、元类
1.什么是元类
类的类就是type,type就是元类 。type是python内置的元类
2.元类的作用
元类是用来产生类的,元类可以控制类的创建过程
3.如何创建元类
01.python内置的元类。比如:type
02.自定义一个元类
4.自定义一个元类,证明元类的作用:
01.作用一,控制类的产生
class MyMetaClass(type): def __init__(self, class_name, class_bases, class_dict): # self, obj print(type(class_name)) if not class_name.istitle(): # .istitle() 表示首字母大写 raise NameError('类的首字母必须大写!') # 主动抛异常 if not class_dict.get('__doc__'): raise TypeError('必须写注释!!!') # 主动抛异常 super().__init__(class_name, class_bases, class_dict) class user(object, metaclass=MyMetaClass): # MyMetaClass(User, (object, ), {'x':10}) '''tank是真的很帅啊,真的舍不得你们啊!!!''' # 这是注释 def __init__(self): pass x = 10 pass obj = user()
结果:
出错,因为user 中的u不是大写
02、元类产生类和类的空对象
class MyMetaClass(type): def __init__(self, class_name, class_bases, class_dict): # self是User print(self) print(type(class_name)) # 是一个字符串 表示类名 print(type(class_bases)) # 是一个元组 表示基类 print(type(class_dict)) # 是一个字典 表示的类的名称空间 if not class_name.istitle(): raise NameError('类的首字母必须大写!') if not class_dict.get('__doc__'): raise TypeError('必须写注释!!!') super().__init__(class_name, class_bases, class_dict) def __call__(self, *args, **kwargs): # self是User print(self) obj = object.__new__(self) # 调用父类object中的__new__来产生一个空对象 print(obj) self.__init__(User,*args, **kwargs) return obj class User(object, metaclass=MyMetaClass): # User继承的父类有object和MyMetaClass '''tank是真的很帅啊,真的舍不得你们啊!!!''' def __init__(self): pass x = 10 pass def __call__(self): pass obj = User() # User是类名,是一个对象。由元类产生。所以User()触发元类中的__call__ # 会把(User(类名), (object, )(基类), {'x':10})。(object, ) 是一个元组 print(User.__dict__) # User是类名,也是一个对象。里面有:注释,函数,x=10 print(obj.__dict__) # obj是一个对象,此时是空的
5、如何产生类的:
1) 通过class关键字产生类
2) 通过调用type类: type() ---> obj ---> Chinese
三、sql的注入问题
import pymysql conn = pymysql.connect( user = 'root', passwd = '123456', db = 'day36', host = '127.0.0.1', port = 3306, charset = 'utf8' ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 获取用户输入的用户名和密码 然后取数据库中校验 username = input('username>>>:').strip() password = input('password>>>:').strip() # sql = "select * from userinfo where name='%s' and password= '%s'"%(username,password) sql = "select * from userinfo where name=%s and password= %s" #只能用%s 去占位 print(sql) cursor.execute(sql,(username,password))
cursor.execute(sql,*args) # 参数 只能识别%s res = cursor.fetchall() if res: print(res) else: print('username or password error!') """ sql注入问题 利用特殊符号和注释语法 巧妙的绕过真正的sql校验 关键性的数据 不要自己手动去拼接 而是交由execute帮你去做拼接
四、python连接数据库
第一步:导入pymysql模块
第二步:连接数据库
第三步:获取游标对象 ----> 游标:是用来提交sql命令的。代码: .cursor()
第四步:通过execute 用来提交sql语句
第五步:提交后,通过cursor_obj对象.fetchall() 获取sql语句查询到的结果
第六步:关闭游标:cursor_obj.close()
第七步:关闭客户端连接 : client.close()
import pymysql # 连接mysql数据库的模块 client = pymysql.connect( # 连接数据库 host='127.0.0.1', port=3306, # 3306是mysql默认的端口 user='root', password='123', database='db4', charset='utf8', # 此处不能写utf-8 charset 表示编码 autocommit=True #(自动提交确认)针对增删改查操作执行重要程度偏高。必须有一步queren 操作 ) print(client) cursor_obj = client.cursor(pymysql.cursors.DictCursor) # 获取游标对象 ----> 游标:是用来提交sql命令的。代码: .cursor() #cursor_obj.scroll(3,'relative') #相对移动:基于指针所在的位置,往后偏移
#cursor_obj.scroll(1,'absolute') #绝对移动:基于起始位置,往后偏移
sql='select * from user_info' # sql语句 cursor_obj.execute(sql) # 通过execute() 可以提交sql语句 res=cursor_obj.fetchall() # 提交后,通过cursor_obj对象.fetchall() 获取所以sql语句查询到的结果,是一个列表,里面的数据是字典 #res=cursor_obj.fetchone() # 只获取查询结果的中的一条数据
#res=cursor_obj.fetchmany(3) # 指定获取几条数据,如果数字超了也不会报错
#cursor_obj.commit() #(手动提交确认)针对增删改查执行重要程度偏高,必须有一步确认操作
print(res) # res是一个列表 for line in res: print(line) cursor_obj.close() # 关闭游标 client.close() # 关闭客户端连接
例子:创建表,插入数据,更改数据
import pymysql # 连接mysql数据库的模块 client = pymysql.connect( # 1.连接数据库 host='127.0.0.1', port=3306, user='root', password='123', database='db4', charset='utf8', # 此处不能写utf-8 autocommit=True ) print(client) cursor_obj = client.cursor(pymysql.cursors.DictCursor) # 获取游标对象 ----> 游标:是用来提交sql命令的。代码: .cursor() sql = 'create table user(id int, name varchar(16))' sql2 = 'insert into user(id, name) values(1, "tank")' try: sql3 = 'update user set name="tank_is_handsome" where id=1' cursor_obj.execute(sql3) # 通过execute 可以提交sql语句 except Exception as e: print(e) cursor_obj.execute(sql) # 通过execute 可以提交sql语句 cursor_obj.execute(sql2) # 通过execute 可以提交sql语句 cursor_obj.close() # 关闭游标 client.close() # 关闭客户端连接