22 元类技术(面向切片编程)|ORM的实现|抽象类与接口类

2024最新常见200+Java面试题汇总(含答案解析) 14. 接口和抽象类有什么区别?15. Java 中 IO 流分为几种?16. BIO、NIO、AIO 有什么区别?17. Files的常用方法都有哪些? 阅读详情

前情知识补充

hasattr 函数

class ObjectCreator(object):
    pass

my_object = ObjectCreator()

# hasattr用来判断一个对象是否有某个属性,有就是True,没有就是false
print(hasattr(ObjectCreator, 'new_attribute'))

ObjectCreator.new_attribute = 'foo'  # 你可以为类增加属性

print(hasattr(ObjectCreator, 'new_attribute'))

输出:
在这里插入图片描述

setattr函数

这个函数是用来给对象赋属性以及对应的值的

使用的方式:

setattr(object 对象, name 字符串 对象属性, value 属性的值)
>>>class A(object):
...     bar = 1
... 
>>> a = A()
>>> getattr(a, 'bar')          # 获取属性 bar 值
1
>>> setattr(a, 'bar', 5)       # 设置属性 bar 值
>>> a.bar
5

getattr函数

参考链接

基本使用方式

getattr(object 对象, name 对象属性, default 如果不存在则返回的值)

一般用于由用户或者程序自动决定想要访问的属性名时,采用这种方法,并且省去try的异常检测,直接自定义返回值。

样例:

from typing import NamedTuple
 
class Person(NamedTuple):
    '''人类'''
    name: str
    age: int
    job: str
    weight: float
    height: float
 
alex = Person('Alex', 32, 'actor', 60, 178)
 
# 把用户输入的字符串赋值给变量attribute_name
attribute_name = input('''What do you want to know about Alex? 
Enter an attribute name>>>''')
# 注意,上述字符串被传进了这个函数作为第二个参数
# 第三个参数是属性不存在时返回的字符串
print(getattr(alex,attribute_name, 'Sorry, this attribute does not exist.'))

join 函数

参考链接链接

这边只介绍元组:


tuple1 = ('a','b','c')  #定义元组tuple1
'、'.join(tuple1)
输出: a、b、c
 
tuple2 = ('hello','peace','world')  #定义元组tuple2
' '.join(tuple2)
输出:hello peace world

元类技术

先介绍方法,再去介绍相关的概念,感觉比较好理解

使用type创建类

先是关于type的基础介绍:

创建出来的类名称 = type("创建出来的类名称", (元组内部放想要继承的类,), {"print_b": print_b, 字典放类函数})

样例见下:

class A(object):
    num = 100


def print_b(self):
    print(self.num)


@staticmethod
def print_static():
    print("----haha-----")


@classmethod
def print_class(cls):
    print(cls.num)


B = type("B", (A,), {"print_b": print_b, "print_static": print_static,
                     "print_class": print_class})
b = B()
b.print_b()
b.print_static()
b.print_class()

什么是元类(概念总结)

这是因为函数 type 实际上是一个元类。type 就是 Python 在背后用来创建所有类的元类。跟int 一样之所以type全是小写,就是根据于此,int是用来创建整形的变量,type就是用来创建类的类。

__metaclass__属性

python在创建类的时候会经过下面的步骤:

  1. 类 中有__metaclass__这个属性吗?如果是,Python 会通过__metaclass__创建
  2. 如果 Python 没有找到__metaclass__,它会继续在 父类中寻找
    __metaclass__属性,并尝试做和前面同样的操作。
  3. 如果 Python 在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。
  4. 如果还是找不到__metaclass__,Python 就会用内置的 type 来创建这个类对象

使用metaclass 的函数方式进行创建类

def upper_class(class_name, class_parent, class_function: dict):
    """
    这边实现的就是将类元素全部变成大写的
    """
    new_dict = dict()
    for key, function in class_function.items():
        if not key.startswith('__'):
            new_dict[key.upper()] = function

    return type(class_name, class_parent, new_dict)


class Test(object, metaclass=upper_class):
    a = 1


print(Test.a)
print(Test.A)

在这里插入图片描述
输出的结果:
在这里插入图片描述

使用metaclass 的类方式进行创建类

class UpperAttrMetaClass(type):
    # __new__ 是在__init__之前被调用的特殊方法
    # __new__是用来创建对象并返回之的方法
    # 而__init__只是用来将传入的参数初始化给对象
    # 你很少用到__new__,除非你希望能够控制对象的创建
    # 这里,创建的对象是类,我们希望能够自定义它,所以我们这里改写__new__
    # 如果你希望的话,你也可以在__init__中做些事情
    # 还有一些高级的用法会涉及到改写__call__特殊方法,但是我们这里不用
    def __new__(cls, class_name, class_parents, class_attr):
        # 遍历属性字典,把不是__开头的属性名字变为大写
        new_attr = {}
        for name, value in class_attr.items():
            if not name.startswith("__"):
                new_attr[name.upper()] = value
		# 值得关注的是需要用这种形式type.__new__而不是使用 type()
        return type.__new__(cls, class_name, class_parents, new_attr)


# python3的用法
class Foo(object, metaclass=UpperAttrMetaClass):
    bar = 'bip'


print(Foo.BAR)

使用type.__new__而不使用type的原因:链接

自定义元类

正常人不需要,只有在想要看懂框架,特别是深度学习的时候需要搞懂这门技术,自己也不需要这么写OxO

“元类就是深度的魔法,99%的用户应该根本不必为此操心。如果你想搞清楚究竟是否需要用到元类,那么你就不需要它。那些实际用到元类的人都非常清楚地知道他们需要做什么,而且根本不需要解释为什么要用元类。” —— Python 界的领袖 Tim Peter”

元类实现ORM

class ModelMetaclass(type):
    def __new__(cls, name, bases, attrs):
        mappings = dict()
        # 判断是否需要保存
        for k, v in attrs.items():
            # 判断是否是指定的StringField或者IntegerField的实例对象
            if isinstance(v, tuple):
                print('Found mapping: %s ==> %s' % (k, v))
                mappings[k] = v

        # 删除这些已经在字典中存储的属性
        for k in mappings.keys():
            attrs.pop(k)

        # if name == 'User':
        #     attrs.pop('hello')
        
        # 将之前的uid/name/email/password以及对应的对象引用、类名字
        attrs['__mappings__'] = mappings  # 保存属性和列的映射关系
        attrs['__table__'] = name  # 假设表名和类名一致
        return super().__new__(cls, name, bases, attrs)


class Model(object, metaclass=ModelMetaclass):
    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            setattr(self, name, value)

    def save(self):
        fields = []
        args = []
        for k, v in self.__mappings__.items():
            fields.append(v[0])
            args.append(getattr(self, k, None))

        args_temp = list()
        for temp in args:
            # 判断入如果是数字类型
            if isinstance(temp, int):
                args_temp.append(str(temp))
            elif isinstance(temp, str):
                args_temp.append("""'%s'""" % temp)
        sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(args_temp))
        print('SQL: %s' % sql)


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


u = User(uid=12345, name='Michael', email='test@orm.org', password='my-pwd')
print(u.__dict__)
u.save()

建议一步一步调试看看函数的执行流程。

接口类与抽象类

抽象类的定义就是:作为微信支付宝的父类,定义了一个具有支付功能的设计类,但是又没有具体实现,需要子类去实现具体的功能的一种类。

接口类的定义就是:一个接口就是一个类,在这个类当中,我们尽量希望有少 或者 仅有一个方法,也即方法即类,在后面使用的时候,我们使用一个子类去继承一个个接口类,并且都将其实例化到各个类代码当中。

二者使用的场景不同:抽象类希望的是本身具有越多的属性越好,然后子类继承,实例化即可,而接口类希望的是本身方法越少越好,最好自己就是一个行为。

抽象类

同样也需要用到元类技术metaclass,以及需要额外导入一个包:
“from abc import abstractmethod, ABCMeta” 使用内部的装饰器@abstractmethod即可创建出一个抽象属性(意思就是子类需要将其定义其功能,而自己只需要写个名字)

from abc import abstractmethod, ABCMeta


# 使用了抽象方法的类,就是抽象类,Payment就是一个抽象类
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        pass


class Alipay(Payment):
    def pay(self, money):  # 这里类的方法不是一致的pay,导致后面调用的时候找不到pay
        print('支付宝支付了')


# 如果子类中没有实现抽象方法,实例化对象时,就会报错
p = Alipay()

接口类

from abc import abstractmethod, ABCMeta


class WalkAnimal(metaclass=ABCMeta):
    @abstractmethod
    def walk(self):
        pass


class SwimAnimal(metaclass=ABCMeta):
    @abstractmethod
    def swim(self):
        pass


class FlyAnimal(metaclass=ABCMeta):
    @abstractmethod
    def fly(self):
        pass


# 如果正常一个老虎有跑和跑的方法的话,我们会这么做
class Tiger(WalkAnimal, SwimAnimal):
    def walk(self): pass
    def swim(self): pass


t = Tiger()

如上,就不进行解释了。

注意点

注意点:

  1. 抽象类是一个介于类和接口之间的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计。
  2. 在继承抽象类的过程中,我们应该尽量避免多继承;
  3. 而在继承接口的时候,我们反而鼓励你来多继承接口, 一般情况下 单继承 能实现的功能都是一样的,所以在父类中可以有一些简单的基础实现,多继承的情况 由于功能比较复杂,所以不容易抽象出相同的功能的具体实现写在父类中。
CDD数据库文件制作(十一)——服务配置(0x19_DTC Code) 虽然选择Copy和Reference都可以加载DTC,但是如果我们在DTC库中有修改DTC,通过Copy的方式加载的DTC在DTC Table中不会跟着DTC库的修改而自动更新。通过Reference的方式加载的DTC可以自动更新。找到Fault Memory的DTC Table,鼠标放在DTC Table区域,右键点击选择Copy …根据需要(客户协议)勾选响应的19服务子功能。如何创建一个新的DTC code?按照字母下方要素可做一一对应。首先在DTC库中新建DTC。支持10 01/10 03。 阅读详情

相关推荐

【嵌入式硬件】LAN9253说明书(中文版)

LAN9253是一款2/3端口EtherCAT从站控制器,具有双集成以太网PHY,每个PHY包含一个全双工100 BASE-TX收发器,支持100 Mbps(100 BASE-TX)操作。 LAN 9253支持HP Auto-MDIX,允许使用直接连接或交叉LAN电缆。支持EtherCAT P和信号质量指数PHY诊断。 LAN9253包括一个EtherCAT从站控制器,带有8K字节的双端口存储器(DPRAM)和8个现场总线存储器管理单(FMMU)。每个FMMU将逻辑地址映射到物

qq_39200110的博客 2401

22.Django三种风格的模型继承

文章目录 1.Django 中的 model 继承和 Python 中的继承非常相似,只不过你要选择具体的实现方式:让父 model 拥有独立的数据库;还是让父 model 只包含基本的公共信息,而这些信息只能由子 model 呈现。 基,指的是继承了model.Model且没有生成表,而是作为基或公共被其他继承 只要继承了model.Model, 就会生成一个新的表,但是,如果在Meta方法中添加abstract=True,就不会产生新的表,而是作为一个基存放多个表共同拥有的方法和字段等

Daniel 387

开发了一套全面的三相电力系统电气故障诊断系统,利用MATLABSimulink仿真技术和先进的图形用户界面。.zip

1.版本:matlab2014a/2019b/2024b2.附赠案例数据可直接运行。3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

JAVA小白初级到中级水平 经典编程练习题目30道!

JAVA小白初级到中级水平 经典编程练习题目30道!

qqrrjj2011的博客 2305

自己开发轻量级ORM(二)

上一篇简单的对轻量级ORM开发开了个头。这篇主要聊下ORM框架的设计思路。 ORM本质上是对数据库操作的抽象。大体上我将其分为对数据结构的抽象和对执行方法的抽象。 我的ORM设计图: ORM框架需要完成.net数据和数据库中数据的相互转换,以及对SQL语句中经典的增删改查操作的抽象封装。 封装方法代码: 1 using System; 2 using System....

weixin_30586085的博客 121

Hibernate继承实现

版权声明:本文为博主原创文章,如需转载请标注转载地址。 博客地址:http://www.cnblogs.com/caoyc/p/5603724.html   对于继承关系的映射。比如在论坛中文章(Ariticla)有主题型(Topic),有回复型(Reply)。其中Topic都id、title、context、postDate、type(型:如普通、精华、置顶......)...

weixin_30411819的博客 71

Java面试题及答案汇总来啦!快来领取

还有不到两个月就要过年了,过完年紧接着“金三银四”招聘热季就要到了,在过年期间只想着吃吃喝喝玩玩,这习是学不了一点。那就趁着过年前这段时间开始恶补Java面试题,实现弯道超车吧!小编整理出一份非常详细的Java面试题以及答案,有需要的自取哟!

m0_47946173的博客 576

.NET 面试题 - C#基础

http://6.ASP.NET MVC,刚开始接触这个技术的时候我经常不理解他们的名字,我相信许多学http://ASP.NET开发人员开始接触MVC应该也和我一样产生很多为什么,也会误认为认为MVChttp://ASP.NET完全没有关系,是一个全新的Web开发,深入学习后我才知道事实上http://ASP.NET是创建WEB应用的框架而MVC是能够用更好的方法来组织并管理代码的一种更高级架构体系,所以可以称之为http://ASP.NET MVC。功能内聚是最强的内聚,其优点是它的功能明确。

微软Dynamics 365 CRM,Power Apps,Power Platform技术和技能培训 2624

C#基础面试题(附答案)

目录 1.C#中堆和栈的区别? 2.C#中的委托是什么?事件是不是一种委托? 3.C#静态构造函数特点是什么? 4.CTS、CLS、CLR分别作何解释 5.C#中什么是值引用型? 6.请详述在C#中(class)结构(struct)的异同? 7.new关键字的作用 8.int?和int有什么区别 9.C#中值传递引用传递的区别是什么? 10.C#中参数传递 ref out 的区别? 11.C#中什么是装箱和拆箱? 12.C#实现多态的过程中 overload 重载

bt5190的博客 5万+

JAVA】-【JPA】-orm思想及jpa配置

orm思想 建立实体和数据库表的映射,通过操作实例对象达到操作数据库的目的 实现orm思想的框架:mybatis,hibernate, hibernate框架介绍 hibernate是一个全自动的orm框架,对jdbc进行了轻量级封装,叫pojo数据库表建立映射关系,可以自动生成sql语句自动执行。 JPA规范 JPA全称:JAVA Persistence API,级Java持久化API,有sun公司推出的基于orm的规范,内部由接口和抽象类组成。 由hibernate实现..

liuxiaowei 620

[Android]AndroidInject增加sqlite3数据库映射注解(ORM)

以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3623050.html AndroidInject项目是我写的一个使用注解注入来简化代码的开源项目 https://github.com/wangjiegulu/androidInject 今天新增功能如下: 1. 增加对sqlite3数据库的orm注解...

weixin_30888027的博客 58

几点学习linux编程的建议,如何设计一个优雅的RESTFUL的接口

分享一套我整理的面试干货,这份文档结合了我多年的面试官经验,站在面试官的角度来告诉你,面试官提的那些问题他最想听到你给他的回答是什么,分享出来帮助那些对前途感到迷茫的朋友。

2303_77877769的博客 776

持久化模式,第 2 部分: 提高代码重用和改进性能,更多的现代 ORM 工具策略和最佳实践

更多的现代 ORM 工具策略和最佳实践 文档选项打印本页 将此页作为电子邮件发送样例代码英文原文

yzhjisji的专栏 512

.NET和NET CORE 100道基础面试题

1.面向对象的语言特性? A:封装性、继承性、多态性。 2.在.NET中所有的基是? A:Object。 3.在C#中,&和&&的区别? A:&是按位运算符(或取地址运算符),&&是条件运算符(也叫逻辑运算符)。 4.委托声明的关键字是? A:delegate。 5.在.NET中所有可序列化的都被标记为? A:Serializable。 6.一个不想被继承应该? A:标记为sealed。 7.简单描述CLR? A:CLR(Common Langu

极客神殿 1万+

牛客网高质量面试题,2024Java面试避坑指南,不管你工作几年都得看看

2024年金九银十马上要开始了,时间晃眼就过去了,有的人为了金九银十跳槽早早做足了准备,有的人在临阵磨刀,想必屏幕前的你也想在2024年涨薪吧,那么问题来了,怎么才能达到目标呢,不妨跟我来看看为大家盘点整理的一些高频面试问题吧!!!

qq13321123的博客 914

2025 阿里巴巴旗下部门饿了吗 面经 八股盛宴

​ 1. 如何自学Java,学习路径 自学Java可以按照以下路径进行: 基础语法:首先学习Java的基本语法,包括变量、数据型、控制结构、面向对象编程、对象、继承、多态等)。 核心库:掌握Java核心库,如字符串处理、集合框架(List、Set、Map等)、输入输出流、多线程编程等。 开发工具:学习使用开发工具,如Eclipse、IntelliJ IDEA等,以及版本控制工具Git。 数据库:了解数据库基础知识,学习SQL语句,掌握一种关系型数据库如MySQL。 Web开发:学习Servlet

多多的博客 1100

Java面试宝典1.0v

目录 1.什么是面向对象? 2.面向对象 2. ORM框架 2.JDK、JRE、JVM三者区别和联系 3."=="equals 4.final: 修饰符 5.String、Stringbuffer、Stringbuilder区别使用场景 6.重写重载的区别 7.接口和抽象类的区别 8.list和set区别 9.hashCoddeequals 10.ArrayList和LinkedList区别 11.HashMap和HashTable的区别?底层实现是什么? 1...

weixin_45853582的博客 469

Spring 源码系列(23): SpringApplication.run() 启动全流程

本文深入解析了SpringApplication.run()的核心流程,通过源码拆解揭示了从启动到容器就绪的完整生命周期。文章重点分析了三个关键阶段:prepareEnvironment的配置加载逻辑(系统属性>环境变量>配置文件)、createApplicationContext的容器型推断机制(基于classpath判断Web/Reactive/普通应用),以及callRunners的启动后回调特性(按@Order执行初始化任务)。同时澄清了常见误区,如内嵌Tomcat实际在refresh阶段的onR

不才不才不不才的博客 387
上一篇: 21 自定义miniweb框架|闭包装饰器|log输出
下一篇: 23 DRF快速入门+部分源码分析
Micoreal
博客等级 码龄5年 106粉丝 · 178原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值