from datetime import date, datetime
import numbers
classIntField:
#数据描述符
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 <0:
raise ValueError("positive value need")
self.value = value
def __delete__(self, instance):
pass
classNonDataIntField:
#非数据属性描述符
def __get__(self, instance, owner):return self.value
classUser:
age =IntField()
# age =NonDataIntField()classUser:
def __init__(self, name, email, birthday):
self.name = name
self.email = email
self.birthday = birthday
self._age =0
@property
def age(self):return datetime.now().year - self.birthday.year
@age.setter
def age(self, value):
#检查是否是字符串类型
self._age = value
if __name__ =="__main__":
user =User("bobby",1,date(year=1987, month=1, day=1))
user.__dict__["age"]="abc"print(user.__dict__)print(user.age)print(getattr(user,'age'))
user =User("bobby",1,date(year=1987, month=1, day=1))
user.age =30print(user._age)print(user.age)
# {'name':'bobby','email':1,'birthday': datetime.date(1987,1,1),'_age':0,'age':'abc'}
# 34
# 34
# 30
# 34
8.4 __new__和__init__的区别
__new__负责创建对象,__init__负责对象的实例化。
classUser:
def __new__(cls,*args,**kwargs):print(" in new ")returnsuper().__new__(cls)
def __init__(self, name):print(" in init")
pass
a =int()
#new 是用来控制对象的生成过程, 在对象生成之前
#init是用来完善对象的
#如果new方法不返回对象, 则不会调用init函数
if __name__ =="__main__":
user =User(name="bobby")
# 需求
import numbers
classField: # 属性描述符的基类
pass
classIntField(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
classCharField(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")iflen(value)> self.max_length:
raise ValueError("value len excess len of max_length")
self._value = value
classModelMetaClass(type):
def __new__(cls, name, bases, attrs,**kwargs):if name =="BaseModel":returnsuper().__new__(cls, name, bases, attrs,**kwargs)
fields ={}for key, value in attrs.items():ifisinstance(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"]returnsuper().__new__(cls, name, bases, attrs,**kwargs)classBaseModel(metaclass=ModelMetaClass):
def __init__(self,*args,**kwargs):for key, value in kwargs.items():setattr(self, key, value)returnsuper().__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
classUser(BaseModel):
name =CharField(db_column="name", max_length=10)
age =IntField(db_column="age", min_value=1, max_value=100)classMeta:
db_table ="user"if __name__ =="__main__":
user =User(name="bobby", age=28)
user.name ="bobby"
user.age =28
user.save()