一、多重继承
1. Java是单一继承,Python是多重继承。
2. 多重继承的好处是避免了复杂庞大的继承链。
3. 多重继承时,提供基本功能的父类作为继承的第一个类,其他类名最好以MinIn结尾,体现出继承关系。
二、定制类
1.__len__方法:类中实现__len__方法后,类的实例能够通过len()函数获取实例的长度(即__len__方法的返回值)。
2. __str__方法:类中实现__str__方法后,类的实例能够通过print()函数打印出实例的内容(即__str__方法的返回值)。
3. __repr__方法:类中实现__repr__方法后,在交互式命令行输入实例名后,能打印出实例的内容(即__repr__方法的返回值)。
4. 类中实现__iter__和__next__方法后,类的实例能够作用于for var in obj循环。每次循环调用实例obj中的__next__方法。
5. __getitem__方法:实现__getitem__方法后能够使用下标访问类的实例。
6. __getattr__方法:实现__getattr__方法后,访问实例中不存在的属性时,会调用__getattr__方法。
7. __call__方法:通常访问实例方法是类似obj.method()的方式调用。实现__call__方法后,可以通过obj()直接调用__call__方法。
8. 普通函数和实现了__call__方法的类实例,作为callable()函数的参数时,函数返回True。
三、使用枚举类
1. 通过python提供的Enum类,定义常量
from enum import Enum # 从enum.py模块导入Enum类。
weekDay = Enum("WeekDay", ("Mon", "Tue", "Wed", "Thur", "Fri", "Sat", "Sun"))
# weekDay是类的别名;
# WeekDay是类名,该类是继承自Enum类。
2. 访问枚举的方法:
weekDay.Sun #输出WeekDay.Sun
weekDay['Sun'] #输出WeekDay.Sun
weekDay.Sun.value #输出7. 枚举值默认从0开始。
weekDay.(7) #输出WeekDay.Sun
3. 为了方便控制枚举常量的值,可以自己定义枚举类:
from enum import Enum, unique
@unique #@unique装饰器 帮助检查保证没有重复值。
class WeekDay(Enum):
Sun = 0
Mon = 1
Tue = 2
Wed = 3
Thur = 4
Fri = 5
Sat = 6
四、使用元类
1. type()
1.1 动态语言的函数和类的定义,不是在编译时确定的,而是在运行时动态创建的。
1.2 使用type()可以获得类型或变量的类型。类型的类型是type,比如int, list,自定义类等的类型是type。
1.3 type()函数也可以动态创建自定义类。事实上python解释器读取python源码时,遇到class的定义,仅仅是扫描一下class定义的语法,然后通过type()函数创建出class。
Hello = type('helloClass', (object, ), dict(method=func)) # 说明如下:
Hello : 是type()函数定义的类的别名。
helloClass : 是type()函数定义的类名。
(object, ) : 元祖中的object说明helloClass类继承自object。
dict(method=func) : func为自定义的函数,表示将func函数作为helloClass的方法method。
2. metaclass
-
类属性和实例属性
-
对于User类,类属性和实例属性同名,这是必须的吗?-- 必须的。因为需要通过类属性名获取实例属性的值。(也可以不同名,但是save方法中需要进行一次转换)
-
类属性的值是Field类的子类,表示数据库表中字段名和字段类型。
-
同名的实例属性的值是数据库表中字段的值。
-
-
User类继承自Model类。
-
Model类继承自dict类,并且由metaclass重新构造。
-
正因为继承自dict类,所以在创建User类的实例时,才能够使用关键字参数。
-
-
ModelMetaClass中的attrs为User类的类属性。
-
将User类的类属性集中保存在User类的新属性__mapping__中,并删除类User类中原来的属性。
-
-
Model类中的save方法:
-
遍历__mapping__属性中的key和value。key是User类中定义的类属性,value是F ield类的子类的实例。
-
由value中的name属性构成sql语句中的表字段集合。
-
由User类属性key获取User类实例属性的值,构成sql语句的值。
-
由此可见:User类属性和User实例属性必须同名。但是User类属性名和类属性值中的name字段可以不同名。
-
-
代码如下:
class Field(object):
def __init__(self, name, column_type):
self.name = name;
self.column_type = column_type
def __str__(self):
return "<%s : %s>" % (self.__class__.__name__, self.name)
class StringField(Field):
def __init__(self, name):
super(StringField, self).__init__(name, "varchar(100)")
class IntegerField(Field):
def __init__(self, name):
super(IntegerField, self).__init__(name, "bigint")
class ModelMetaClass(type):
def __new__(cls, name, bases, attrs):
if name == 'Model':
return type.__new__(cls, name, bases, attrs)
else:
print("New model : %s" % name)
mappings = dict()
for k, v in attrs.items():
if isinstance(v, Field):
print("table field : %s-%s" % (k, v))
mappings[k] = v
for k in mappings.keys():
attrs.pop(k)
attrs["__mappings__"] = mappings
attrs["__table__"] = name
return type.__new__(cls, name, bases, attrs)
class Model(dict, metaclass = ModelMetaClass):
def __init__(self, **kwargs):
super(Model, self).__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 = []
values = []
for k, v in self.__mappings__.items():
fields.append(v.name)
# values.append(getattr(self, k, None))
values.append(self[k])
sql = "insert into %s(%s) values(%s);" % (self.__table__, ','.join(fields), ','.join( [str(value) for value in values] ))
print(sql)
class User(Model):
id = IntegerField("uid")
name = StringField("username")
passwd = StringField("password")
em = StringField("e-mail")
u1 = User(id=123456, name="lfc", passwd='1q2w3e', em="123456789@qq.com")
u1.save()
输出为:
New model : User
table field : em-<StringField : e-mail>
table field : passwd-<StringField : password>
table field : name-<StringField : username>
table field : id-<IntegerField : uid>
insert into User(e-mail,password,username,uid) values(123456789@qq.com,1q2w3e,lfc,123456);