<Python元类剖析>

1 Python创建对象

1.1 Python层面创建对象

"""测试1"""
class Test1(object):
    def __new__(cls, *args, **kwargs):
        print(f"__new__方法被调用了")
        return object.__new__(cls)
	

t1 = Test1()
# __new__方法被调用了
"""测试2"""
class Test1(object):
    def __new__(cls, *args, **kwargs):
        print(f"__new__方法被调用了")
        return object.__new__(cls)

    def __init__(self,name):
        print(f'{self}被初始化了')
        self.name = name


t1 = Test1('test')
# __new__方法被调用了
# <__main__.Test1 object at 0x000002192A201EB0>被初始化了

在这里插入图片描述
如上图所示,通过一个类对象创建一个实例对象,会先调用类对象的__new__方法,__new__方法会接收一个类对象的引用,在堆中开辟一个空间,创建一个对象,返回这个开辟的堆空间引用。
创建好实例之后,类提供__init__方法对实例进行初始化,初始化方法需要一个self参数,self参数就是__new__方法创建的对象,初始化方法在实例内存空间中添加一些属性。

1.2 C源码层面创建对象

暂略

2 元类

Python的对象模型有两种关系,一种是继承关系,另一种是实例化关系,继承关系维护子类与父类之间的联系,实例化关系维护实例与类(模板)之间的关系

继承关系:obj.base

class A:
    pass


class B(A):
    pass


class C(B):
    pass


print(C.__base__)
print(C.__base__.__base__)
print(C.__base__.__base__.__base__)

#<class '__main__.B'>
#<class '__main__.A'>
#<class 'object'>

实例化关系:obj.class

a = 5

print(a.__class__)

print(a.__class__.__class__)

print(a.__class__.__class__.__class__)

#<class 'int'>
#<class 'type'>
#<class 'type'>

在这里插入图片描述

本文不过多说继承关系,主要说实例化关系,实例是通过类实例化产生的,这个是很好理解的,Python一切皆对象,类是通过什么创造出来的呢?通过上面的代码执行结果可以看到,类是通过type类创建的,type类也叫元类,type类也是通过type创建出来的。

type类定义在Python源码的builtins.py模块中

2.1 Python层面类如何被创建

class A(object):
    A_ = 'I am a class!'

    def show(self):
        print(self.A_)


def show(self):
    print(self.B_)


B = type('B', (object,), {'B_': 'I am B class!', 'show': show})

print(A)
print(B)

A().show()
B().show()
#<class '__main__.A'>
#<class '__main__.B'>
#I am a class!
#I am B class!

当使用class语法糖创建一个对象时,其实在Python内部执行的是type(),Python真的足够灵活,他的动态性真的太好了

2.2 给类加”装饰器“

如果你想不改变函数时增加一个功能,那么毫无疑问的会想到装饰器,当你想规范类的行为时,就可以应用元类,python的类默认都是通过typ类创建出来的,自定义一个类如果继承了type,那么这个类就可以做为一个元类,规范很多类。

元类创造类


class UpperAttrType(type):
    """
    因为继承了元类,UpperAttrType可以做为其他类的元类
    """
    pass


class A(object,metaclass=UpperAttrType):
    """
    class A 继承 object
    UpperAttrType为A类的元类
    """
    pass


print(A.__class__)
# <class '__main__.UpperAttrType'>

元类创造类的过程

class UpperAttrType(type):
    """
    因为继承了元类,UpperAttrType可以做为其他类的元类
    """
    def __new__(cls, *args, **kwargs):
        print('我被执行了')
        __mapping__ = dict()
        for i in args:
            if isinstance(i,dict):
                for k,v in i.items():
                    if not str(k).startswith('__'):
                        __mapping__[str(k).upper()] = v
        return type('A',(),__mapping__)


class A(object,metaclass=UpperAttrType):
    """
    class A 继承 object
    UpperAttrType为A类的元类
    """
    age = 11
    

a = A()

print(hasattr(a,'age'))
# False
print(hasattr(a,'AGE'))
# True

创建类,第一步是执行元类的__new__方法,__new__方法要返回一个类,在返回的过程中对类属性进行修改,类似函数的装饰器。

3 元类的应用->ORM

ORM (object relationship mapping),对象关系映射,在django和sqlalchemy中都实现了ORM框架

在这里插入图片描述
在应用中使用sql语句对数据库进行操作会比较麻烦,如果使用类和对象对数据库进行操作,就会免去写大量的SQL语句。

V1.0

class ModelMateClass(type):
    def __new__(cls, name, bases, attrs):
        __mapping__ = dict()
        for k, v in attrs.items():
            if isinstance(v, tuple):
                __mapping__[k] = v
        for k in __mapping__.keys():
            attrs.pop(k)
        attrs['mapping'] = __mapping__
        attrs['__tablename__'] = name
        return type.__new__(cls, name, bases, attrs)


class User(metaclass=ModelMateClass):
    uid = ('uid', 'unsigned int')
    name = ('username', 'varchar(30)')
    email = ('email', 'varchar(30)')
    password = ('password', 'varchar(30)')

    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

    def save(self):
        fields = [k for k, v in User.mapping.items()]
        tags = [v for k, v in self.__dict__.items()]
        sql = f'insert into %s (%s) values (%s)' % (User.__tablename__, ','.join(fields), ','.join(tags))
        print(sql)


u1 = User(uid="1", name="zs", email="xxx@xx.com", password="123")

u1.save()

# insert into User (uid,name,email,password) values (1,zs,xxx@xx.com,123)

V1.1

#升级save
    def save(self):
        fields = [k for k, v in User.mapping.items()]
        tags = [v for k, v in self.__dict__.items()]
        tags_ = []
        for tag in tags:
            if isinstance(tag, int):
                tags_.append(f"""{tag}""")
            elif isinstance(tag, str):
                tags_.append(f"""'{tag}'""")
        sql = f'insert into %s (%s) values (%s)' % (User.__tablename__, ','.join(fields), ','.join(tags_))
        print(sql)
# insert into User (uid,name,email,password) values (1,'zs','xxx@xx.com','123')

V1,2

class Model(metaclass=ModelMateClass):
    pass

class User(Model):
    uid = ('uid', 'unsigned int')
    name = ('username', 'varchar(30)')
    email = ('email', 'varchar(30)')
    password = ('password', 'varchar(30)')

    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

    def save(self):
        fields = [k for k, v in User.mapping.items()]
        tags = [v for k, v in self.__dict__.items()]
        tags_ = []
        for tag in tags:
            if isinstance(tag, int):
                tags_.append(f"""{tag}""")
            elif isinstance(tag, str):
                tags_.append(f"""'{tag}'""")
        sql = f'insert into %s (%s) values (%s)' % (User.__tablename__, ','.join(fields), ','.join(tags_))
        print(sql)


class Book(Model):
    bookid = ('bookid', 'unsigned int')
    name = ('bookname', 'varchar(30)')


    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

    def save(self):
        fields = [k for k, v in Book.mapping.items()]
        tags = [v for k, v in self.__dict__.items()]
        tags_ = []
        for tag in tags:
            if isinstance(tag, int):
                tags_.append(f"""{tag}""")
            elif isinstance(tag, str):
                tags_.append(f"""'{tag}'""")
        sql = f'insert into %s (%s) values (%s)' % (Book.__tablename__, ','.join(fields), ','.join(tags_))
        print(sql)

封装之后的样子是不是感觉很眼熟

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kobe_OKOK_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值