# -*- coding:UTF-8 -*- __autor__ = 'zhouli' __date__ = '2018/12/3 23:13' def create_class(name): if name == "user": class User: def __str__(self): return "user" return User # 这一步很关键一定要把类给return回去 elif name == "company": class Company: def __str__(self): return "company" return Company if __name__ == "__main__": MyClass = create_class("user") my_obj = MyClass() print(my_obj)
结果是user,这个就是动态的创建出来的类。
不过在此做一个补充说明:很多人不明白为什么使用
if __name__ == "__main__":
因为这样会保证这个脚本被调用时候不会被自动执行
但这样动态的创建类也不是太灵活,那就可以采用type类了
type一般用来获取某一个对象的类型的,第二点就是type可以用来创建类的
如何动态的创建类呢?
# -*- coding:UTF-8 -*- __autor__ = 'zhouli' __date__ = '2018/12/3 23:25' # type动态创建类 # User = type("User", (), {}) # 第一个参数传递的是类的名称,第二个参数是继承的基类,不继承直接写个空元祖,第三个参数是传入属性,不写传一个空字典 if __name__=="__main__": User = type("User", (), {}) my_obj = User() print(my_obj) """ <__main__.User object at 0x025A4A50> """
为User添加属性
if __name__=="__main__": User = type("User", (), {"name":"user"}) my_obj = User() print(my_obj.name) """ user """
这个就和
# -*- coding:UTF-8 -*- __autor__ = 'zhouli' __date__ = '2018/12/3 23:13' def create_class(name): if name == "user": class User: name = "user" def __str__(self): return "user" return User # 这一步很关键一定要把类给return回去 elif name == "company": class Company: def __str__(self): return "company" return Company if __name__ == "__main__": MyClass = create_class("user") my_obj = MyClass() print(my_obj.name)
是一样的了
但是我们创建类的时候不仅仅有类的属性,实际还有类的方法,那如何定义呢?
很简单:定义一个函数,记住参数一定要是self:
def say(self): return "i am user" # return self.name
然后在属性中加入{"say": say}
完整如下:
def say(self): # return "i am user" return self.name + 'test' if __name__ == "__main__": User = type("User", (), {"name": "user", "say": say}) # 是函数的名称,不是调用,不要加() my_obj = User() print(my_obj.say()) """ usertest """
那如果User需要继承一个基类呢?
class BaseClass: def answer(self): return '****' if __name__ == "__main__": User = type("User", (BaseClass,), {"name": "user", "say": say}) # 是函数的名称,不是调用,不要加() my_obj = User() print(my_obj.answer()) """ **** """
别忘了元祖后的一个逗号
那什么才是元类?
元类是创建类的类!
编码时很少会采用type创建类,一般使用MetaClass(type)类名可以自定义,但继承type了他就是元类了
class MetaClass(type): def __new__(cls, *args, **kwargs): return super().__new__(cls, *args, **kwargs) from collections.abc import * # 什么是元类, 元类是创建类的类 对象<-class(对象)<-type class User(metaclass=MetaClass): # 指定控制实例化过程的元类 def __init__(self, name): self.name = name def __str__(self): return "user" # python中类的实例化过程,会首先寻找metaclass,通过metaclass去创建user类 # 去创建类对象,实例
类什么也不继承的时候,type会去创建类对象,实例。
那么元类到底有什么作用呢?
例:自定义ORM(自我仿制乞丐版Django的ORM)
# 需求 import numbers class Field: pass class IntField(Field): # 数据描述符 def __init__(self, db_column, min_value=None, max_value=None): self._value = None # 这里采用_单下划线模式,指明这是一个内部的变量,不希望采用self._value方式访问 self.min_value = min_value self.max_value = max_value self.db_column = db_column if min_value is not None: if not isinstance(min_value, numbers.Integral): raise ValueError("min_value must be int") elif min_value < 0: raise ValueError("min_value must be positive int") if max_value is not None: if not isinstance(max_value, numbers.Integral): raise ValueError("max_value must be int") elif max_value < 0: raise ValueError("max_value must be positive int") if min_value is not None and max_value is not None: if min_value > max_value: raise ValueError("min_value must be smaller than max_value") def __get__(self, instance, owner): return self._value def __set__(self, instance, value): if not isinstance(value, numbers.Integral): raise ValueError("int value need") if value < self.min_value or value > self.max_value: raise ValueError("value must between min_value and max_value") self._value = value class CharField(Field): def __init__(self, db_column, max_length=None): self._value = None self.db_column = db_column if max_length is None: raise ValueError("you must spcify max_lenth for charfiled") self.max_length = max_length def __get__(self, instance, owner): return self._value def __set__(self, instance, value): if not isinstance(value, str): raise ValueError("string value need") if len(value) > self.max_length: raise ValueError("value len excess len of max_length") self._value = value class ModelMetaClass(type): def __new__(cls, name, bases, attrs, **kwargs): # 在这里就和用type生成类是一样的用法,attr是{}是类的方法,bases是(),name是类名 if name == "BaseModel": return super().__new__(cls, name, bases, attrs, **kwargs) fields = {} for key, value in attrs.items(): if isinstance(value, Field): fields[key] = value attrs_meta = attrs.get("Meta", None) _meta = {} # db_table = name.lower() if attrs_meta is not None: table = getattr(attrs_meta, "db_table", None) # 利用反射,找不到置为None if table is not None: db_table = table _meta["db_table"] = db_table attrs["_meta"] = _meta attrs["fields"] = fields del attrs["Meta"] return super().__new__(cls, name, bases, attrs, **kwargs) class BaseModel(metaclass=ModelMetaClass): def __init__(self, *args, **kwargs): for key, value in kwargs.items(): setattr(self, key, value) return super().__init__() def save(self): # 拼凑save的字符串 fields = [] values = [] for key, value in self.fields.items(): db_column = value.db_column if db_column is None: db_column = key.lower() fields.append(db_column) value = getattr(self, key) values.append(str(value)) sql = "insert {db_table}({fields}) value({values})".format(db_table=self._meta["db_table"], fields=",".join(fields), values=",".join(values)) pass class User(BaseModel): # 因为本身没有metaclass,他会首先查找父类的metaclass name = CharField(db_column="name", max_length=10) age = IntField(db_column="age", min_value=1, max_value=100) class Meta: db_table = "user" if __name__ == "__main__": user = User(name="bobby", age=28) # 这样是先走BaseModel的,将值变为下面注释的样子 # user.name = "bobby" # 这样是先走User的 # user.age = 28 # 这样是先走User的 user.save()