简单的动态获取类的方法
def create_class(name): if name == "user": class User: def __str__(self): return "user" return User elif name == "company": class Company: def __str__(self): return "company" return Company if __name__ == "__main__": MyClass = create_class("user") my_obj = MyClass() print(type(my_obj)) # <class '__main__.create_class.<locals>.User'>
使用type动态创建类
一
# type动态创建类 def say(self): return "i am saying" # 第一个参数是类名,第二个参数是基类,第三个参数是类的属性 User = type("User", (), {"name":"wanghw","say":say}) my_obj = User() print(my_obj) # <__main__.User object at 0x109ec30f0> print(my_obj.name) # wanghw print(my_obj.say()) # i am saying
二
def say(self): return "i am user" # return self.name class BaseClass(): def answer(self): return "i am baseclass" if __name__ == "__main__": # BaseClass后面的逗号必须有 User = type("User", (BaseClass, ), {"name":"user", "say":say}) my_obj = User() print(my_obj) # <__main__.User object at 0x109fd7d68> print(my_obj.answer()) # i am baseclass
使用元类创建类 —— 实际中的用法 ***
##### python中类的实例化过程:会首先寻找metaclass,通过metaclass去创建user类 去创建类对象,实例 ### 继承type class MetaClass(type): def __new__(cls, *args, **kwargs): return super().__new__(cls, *args, **kwargs) # 元类是创建类的类 对象<-class(对象)<-type class User(metaclass=MetaClass): def __init__(self, name): self.name = name def __str__(self): return self.name if __name__ == "__main__": user = User("wanghw") print(user) # wanghw
使用元类实现自定义的ORM
# 需求 import numbers class Field: pass class IntField(Field): # 数据描述符 def __init__(self, db_column, min_value=None, max_value=None): self._value = None 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): 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) 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): 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): 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="whw", age=28) # user.name = "whw" # user.age = 28 user.save()
~~~