1、import搜索路径
import sys sys.path从上面的目录中依次查找要导入的模块文件,列表中的路径的先后顺序代表了python解释器在搜索模块时的先后顺序。
程序执行时添加新的模块路径
sys.path.append("/xx/oo") sys.path.insert(0, "/yy/zz") sys.pathimport aa
1、让python解释器加载 aa .py2、在当前模块定义一个aa变量指向刚刚加载的模块import aa as AA --> 这样是为了防止程序有其他变量与aa重名,所以导入时给他换了一个名字。
2、重新导入模块
模块被导入之后,import module 不能重新导入模块,重新导入需要reload
import xxoo xxoo.test() ----test----2导入xxoo.py模块,模块中包括一个test函数
import xxoo xxoo.test() ----test----2对xxoo.py的test函数进行修改后,在进行导入,执行test函数,返现结果并没有改变,这是因为import只会导入一次,即使模块进行了修改,import也不会重新导入。
使用reload进行重新导入
from imp import reload reload(xxoo) xxoo.test() ----test----2多模块开发时模块导入的一个错误案例
from common import RECV_DATA_LIST from common import HANDLE_FLAG print(HANDLE_FLAG) print("HANDLE_FLAG地址:", id(HANDLE_FLAG)) def handle_msg(): """模拟处理数据""" print(">>handle_msg") for i in RECV_DATA_LIST: print(i) # HANDLE_FLAG = True # 这样,HANDLE_FLAG就是handle_msg()函数里的一个局部变量,别的函数无法访问 global HANDLE_FLAG print("全局变量HANDLE_FLAG的地址:", id(HANDLE_FLAG)) HANDLE_FLAG = True print("修改HANDLE_FLAG值后的地址:", id(HANDLE_FLAG)) def test_handle_msg(): """模拟测试处理数据""" print(">>test_handle_msg") if HANDLE_FLAG: # 无法访问handle_msg里的HANDLE_FLAG,除非在handle_msg里的HANDLE_FLAG前加上global print("已经处理完") else: print("未处理完") handle_msg() test_handle_msg() False HANDLE_FLAG地址: 1399397680 >>handle_msg 全局变量HANDLE_FLAG的地址: 1399397680 修改HANDLE_FLAG值后的地址: 1399397648 >>test_handle_msg 已经处理完正确案例,部分代码见下图
from handle_msg import * from recv_msg import * from imp import reload reload(common) recv_msg() test_recv_msg() recv_msg_next() handle_msg() test_handle_msg() recv_msg_next() >>recv_msg >>test_recv_msg [0, 1, 2, 3, 4] >>recv_msg_next 数据未处理完,等待中.... >>handle_msg 0 1 2 3 4 >>test_handle_msg 已经处理完 >>recv_msg_next 数据处理完,准备接收其他信息类是创建一个对象的代码块。同样,类也是一个对象,python中一切皆对象。元类就是创建类的“东西”。
元类(万物之主)–>类对象–>实例对象
1、动态创建类
# 使用class关键字 def choose_class(name): if name == "foo": class Foo(): pass return Foo else: class Boo(): pass return Boo myclass = choose_class("foo") print(myclass) print(myclass()) <class '__main__.choose_class.<locals>.Foo'> <__main__.choose_class.<locals>.Foo object at 0x000001C13558F1D0> # 使用type创建类 # type还有一个完全不同的特性,动态创建类,格式:type(类名,(针对继承问题,由父类名组成的元组,可以为空),{包含属性的字典,名称和值}) Myclass = type("Myclass", (), {}) print(Myclass) <class '__main__.Myclass'>使用type创建一个带属性的类
class Foo(): pass Myclass = type("Myclass", (Foo, ), {"name": "zhangsan", "age": 18}) print(hasattr(Myclass, "name")) Myclass.__dict__ True mappingproxy({'__doc__': None, '__module__': '__main__', 'age': 18, 'name': 'zhangsan'})使用type创建带方法的类
# 实例方法 def instance_f(self): print("this is instance function") # 静态方法 @staticmethod def static_f(): print("this is static function") # 类方法 @classmethod def class_f(cls): print("this is class function") Myclass = type("Myclass", (), {"instance_f": instance_f, "static_f": static_f, "class_f": class_f}) mc = Myclass() mc.instance_f() mc.static_f() mc.class_f() print(Myclass.__dict__) this is instance function this is static function this is class function {'class_f': <classmethod object at 0x000001C135598358>, '__doc__': None, 'static_f': <staticmethod object at 0x000001C135598320>, '__module__': '__main__', 'instance_f': <function instance_f at 0x000001C135569B70>, '__dict__': <attribute '__dict__' of 'Myclass' objects>, '__weakref__': <attribute '__weakref__' of 'Myclass' objects>}使用__metaclass__属性创建一个类
class Foo(): __metaclass__ = someting... ...python创建类Foo的过程:在执行class Foo()这句时,Foo类还没有在内存中创建,python会在类中寻找__metaclass__属性, 如果找到了,python会用它创建类,如果没有找到,就会用内建的type来创建这个类。class
Foo(Bar): passpython做了如下的操作:
1、Foo中有__metaclass__这个属性吗?如果是,python会通过__metaclass__创建一个名字为Foo的类(对象) 2、如果python没有找到__metaclass__,他会继续在Bar(父类)中寻找__metaclass__属性,并尝试做前面的同样操作 3、如果在任何父类中都找不到__metaclass__,他就会在模块层次中去寻找__metaclass__,并尝试做同样的操作 4、还是没找到的话,python就会用内置的type来创建这个类对象 # python2中 def upper_attr(class_name, class_parents, class_attr): new_attr = {} for name, value in class_attr.items(): if not name.startswith("__"): new_attr[name.upper()] = value return type(class_name, class_parents, new_attr) class Foo(): __metaclass__ = upper_attr name = "zhangsan" age = 18 f = Foo() print(Foo.__dict__) {'age': 18, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__doc__': None, '__module__': '__main__', 'name': 'zhangsan', '__metaclass__': <function upper_attr at 0x000001C135569BF8>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>} # python3中 def upper_attr(class_name, class_parents, class_attr): new_attr = {} for name, value in class_attr.items(): if not name.startswith("__"): new_attr[name.upper()] = value return type(class_name, class_parents, new_attr) # 在创建Foo类对象之间,python会先执行metaclass指向的方法,<==> upper_attr("Foo", (Bar,), {"name": "zhangsan", "age": 18}) class Foo(metaclass=upper_attr): name = "zhangsan" age = 18 f = Foo() print(hasattr(Foo, "name")) print(hasattr(Foo, "NAME")) print(f.NAME) print(Foo.__dict__) False True zhangsan {'NAME': 'zhangsan', 'AGE': 18, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}上例中使用函数当作元类,可以使用类来当作元类
class Upper_attr_class(type): def __new__(cls, class_name, class_parents, class_attr): new_attr = {} for name, value in class_attr.items(): if not name.startswith("__"): new_attr[name.upper()] = value return super().__new__(cls, class_name, class_parents, new_attr) # super继承type类 # return type(class_name, class_parents, new_attr) # 这个不是oop,因为直接调用了type # return type.__new__(cls, class_name, class_parents, new_attr) # 复用type.__new__()方法 class Foo(metaclass=Upper_attr_class): # Foo<==>Upper_attr_class("Foo", (), {"name": "lisi", "age": 30}) name = "lisi" age = 30 foo = Foo() print(hasattr(Foo, "name")) print(hasattr(Foo, "AGE")) print(foo.AGE) print(Foo.__dict__) False True 30 {'NAME': 'lisi', 'AGE': 30, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}ORM模型是在python编程语言后端web框架Django的核心思想,“Object Relational Mapping”,即对象-关系映射。
简单的说,创建一个实例对象,用创建它的类名当作数据表名,用创建它的类属性对应数据表的字段,当对这个实例对象操作时,能执行对应MySQL语句。
使用元类实现ORM模型
1、创建一个Field类,用于保存数据表的字段名和字段类型
class Field(): def __init__(self, name, column_type): self.name = name self.column_type = column_type def __str__(self): # 使用print时,返回下面的形式 return "<%s: %s>" % (self.__class__.__name__, self.name) class StringField(Field): def __init__(self, name): super().__init__(name, "varchar(100)") class IntegerField(Field): def __init__(self, name): super().__init__(name, "bigint") s = StringField('name') print(s.__class__.__name__) # 打印创建s实例对象的类的名字 print(s.__str__) # 打印s时,会调用父类的__str__方法 StringField <bound method Field.__str__ of <__main__.StringField object at 0x000001C135581208>>2、定义元类,用于创建Model对象
class Modelmetaclass(type): def __new__(cls, class_name, class_parents, class_attr): if class_name == "Model": return super().__new__(cls, class_name, class_parents, class_attr) mappings = {} for key, val in class_attr.items(): if isinstance(val, Field): # isinstance() 会认为子类是一种父类类型,考虑继承关系。 # 保存类属性和列的映射关系到mappings字典 print("Found mapping: %s ==> %s" % (key, val)) # 因为val=IntegerField('uid'),会调用Field类里的__str__方法 mappings[key] = val for k in mappings.keys(): # 将类属性移除,使定义的类字段不污染User类属性,只在实例中可以访问这些key class_attr.pop(k) class_attr['__mappings__'] = mappings class_attr['__table__'] = class_name.lower() return super().__new__(cls, class_name, class_parents, class_attr) a = {"key": 12} print(a.items()) print(a.keys()) print(a.values()) dict_items([('key', 12)]) dict_keys(['key']) dict_values([12]) class Model(dict, metaclass=Modelmetaclass): def __init__(self, **kwargs): # print(kwargs) # {'password': '123', 'email': '110@sina.com', 'name': 'laozhao', 'uid': 1} super().__init__(**kwargs) def __getattr__(self, key): try: return self[key] except KeyError: raise AttributeError("'Model' object has no attribute '%s'" % key) def __setattr__(self, key, value): self[key] = value def save(self): fields = [] params = [] for k, v in self.__mappings__.items(): # print(k,v) # email <StringField: email> password <StringField: password> uid <IntegerField: uid> name <StringField: username> # print(getattr(self, k, None)) # 1 110@sina.com 123 laozhao fields.append(k) params.append(getattr(self, k, None)) sql = "insert into {0} {1} values {2}".format(self.__table__, tuple(fields), tuple(params)) print("SQL: %s" % sql) print("params: %s" % str(params))使用定义好的ORM接口
class User(Model): # User = Modelmetaclass("User", (Model,), {"uid": IntegerField('uid'), "name": StringField('username'), ...}) uid = IntegerField('uid') name = StringField('username') email = StringField('email') password = StringField('password') u = User(uid=1, name='laozhao', email="110@sina.com", password="123") # 因为Model继承了dict类,这些值都会以字典格式保存 u.save() Found mapping: password ==> <StringField: password> Found mapping: email ==> <StringField: email> Found mapping: name ==> <StringField: username> Found mapping: uid ==> <IntegerField: uid> SQL: insert into user ('email', 'name', 'uid', 'password') values ('110@sina.com', 'laozhao', 1, '123') params: ['110@sina.com', 'laozhao', 1, '123']