Discuss / Python / 我实现了orm,发现有错,廖老师审核下,看看是不是错了

我实现了orm,发现有错,廖老师审核下,看看是不是错了

Topic source

_ForrestGump

#1 Created at ... [Delete] [Delete and Lock User]

class Model(dict): class User(Model, metaclass=ModelMetaClass): metaclass=ModelMetaClass应该放在User中, 判断条件需要改成if not Model in bases:

个人代码测试可用

class Field(object):

    def __init__(self, name, columnType):
        self.name = name
        self.columnType = columnType

    def __str__(self):
        return "<%s, %s>" % (self.__class__.__name__, self.name)

class StringField(Field):

    def __init__(self, name):
        super(StringField, self).__init__(name, 'varchar(32)')

class IntegerField(Field):

    def __init__(self, name):
        super(IntegerField, self).__init__(name, 'int(11)')

class ModelMetaClass(type):

    def __new__(cls, name, bases, attrs):
        if not Model in bases:
            return type.__new__(cls, name, bases, attrs)
        print("Found Model %s" % name)
        #print(attrs)
        mappings = dict()
        for k, v in attrs.items():
            if isinstance(v, Field):
                mappings[k] = v
                print("Found mappings %s => %s" % (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):

    def __init__(self, **kw):
        super(Model, self).__init__(**kw)

    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError:
            raise AttributeError(r"Model has no attribute %s" % key)

    def __setattr__(self, key, value):
        self[key] = value

    def save(self):
        fields = []
        args = []
        for k, v in self.__mappings__.items():
            fields.append(v.name)
            args.append(str(getattr(self, k)))
        sql = " insert into %s (%s) values (%s) " % (self.__table__, ','.join(fields), ','.join(args))
        print("SQL: %s" % sql)

class User(Model, metaclass=ModelMetaClass):

    id = IntegerField("id")
    name = StringField("name")
    pwd = StringField("password")
    age = IntegerField("age")

user = User(id=12345, name="Forest", pwd="my-pwd", age=26)
user.save()

chaleaoch

#2 Created at ... [Delete] [Delete and Lock User]

你俩的代码都没错。我和你的想法是一样的。 但是在实际设端点的调试过程中,我发现廖老师的写法也能中断跳进去。 只是不是很清除原因。

希望能得到聊老师的解答。

也欢迎共同探讨。

Model上添加元类更加合理,总不能每次生成子类User都写一堆metaclass='...'这样的代码吧。

元类调用的机制是:创建类的时候会在自己的身上找元类也就是在使用class定义类的时候传入的metaclass关键字参数,通常情况下我们定义一个类这样写class Person(object),实际上这里缺省的metaclass为系统提供的class Person(object,metaclass='')。 没有找到就从父类上找,一直向上到object还是没有找到就使用内置的元类来生成类,也就是调用type('name',base,attrs),或者调用type.new(cls,name,base,attr),cls是类本身。

这里判断:

if name == 'Model':
    return type.__new__(cls,name,base,attr)

if not Model in base:
    return type.__new__(cls,name,base,attr)

效果是一样的,都是为了保证生成Model子类的时候使用ModelMetaclass,生成Model自身的时候使用系统元类。

  • 后者是在生成Model类的时候直接调用系统提供的元类,不使用自定义的元类,其衍生的子类使用自定义的元类。因为Model类和其没有另外指定metaclass的子类都会来找这个ModelMetaclass来生成类

  • 前者表示如果你这个类不是Model的子类就也直接调用系统元类,并不会调用专门为Model子类写的元类


  • 1

Reply