圣宠宠物网站建设,湖南天辰建设责任公司网站,做一个网站怎么做,给自己的网站起名字文章目录 前情知识补充hasattr 函数setattr函数getattr函数join 函数 元类技术使用type创建类什么是元类#xff08;概念总结#xff09;\_\_metaclass\_\_属性使用metaclass 的函数方式进行创建类使用metaclass 的类方式进行创建类 自定义元类 元类实现ORM接口类与抽象类抽象… 文章目录 前情知识补充hasattr 函数setattr函数getattr函数join 函数 元类技术使用type创建类什么是元类概念总结\_\_metaclass\_\_属性使用metaclass 的函数方式进行创建类使用metaclass 的类方式进行创建类 自定义元类 元类实现ORM接口类与抽象类抽象类接口类注意点 前情知识补充
hasattr 函数
class ObjectCreator(object):passmy_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 值
1setattr(a, bar, 5) # 设置属性 bar 值a.bar
5getattr函数
参考链接
基本使用方式
getattr(object 对象, name 对象属性, default 如果不存在则返回的值)一般用于由用户或者程序自动决定想要访问的属性名时采用这种方法并且省去try的异常检测直接自定义返回值。
样例
from typing import NamedTupleclass Person(NamedTuple):人类name: strage: intjob: strweight: floatheight: floatalex 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、ctuple2 (hello,peace,world) #定义元组tuple2.join(tuple2)
输出hello peace world元类技术
先介绍方法再去介绍相关的概念感觉比较好理解
使用type创建类
先是关于type的基础介绍
创建出来的类名称 type(创建出来的类名称, (元组内部放想要继承的类,), {print_b: print_b, 字典放类函数})样例见下
class A(object):num 100def 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在创建类的时候会经过下面的步骤
类 中有__metaclass__这个属性吗如果是Python 会通过__metaclass__创建如果 Python 没有找到__metaclass__它会继续在 父类中寻找 __metaclass__属性并尝试做和前面同样的操作。如果 Python 在任何父类中都找不到__metaclass__它就会在模块层次中去寻找__metaclass__并尝试做同样的操作。如果还是找不到__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()] functionreturn type(class_name, class_parent, new_dict)class Test(object, metaclassupper_class):a 1print(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, metaclassUpperAttrMetaClass):bar bipprint(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, metaclassModelMetaclass):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(uid12345, nameMichael, emailtestorm.org, passwordmy-pwd)
print(u.__dict__)
u.save()建议一步一步调试看看函数的执行流程。
接口类与抽象类
抽象类的定义就是作为微信支付宝的父类定义了一个具有支付功能的设计类但是又没有具体实现需要子类去实现具体的功能的一种类。
接口类的定义就是一个接口就是一个类在这个类当中我们尽量希望有少 或者 仅有一个方法也即方法即类在后面使用的时候我们使用一个子类去继承一个个接口类并且都将其实例化到各个类代码当中。
二者使用的场景不同抽象类希望的是本身具有越多的属性越好然后子类继承实例化即可而接口类希望的是本身方法越少越好最好自己就是一个行为。
抽象类
同样也需要用到元类技术metaclass以及需要额外导入一个包 “from abc import abstractmethod, ABCMeta” 使用内部的装饰器abstractmethod即可创建出一个抽象属性意思就是子类需要将其定义其功能而自己只需要写个名字
from abc import abstractmethod, ABCMeta# 使用了抽象方法的类就是抽象类Payment就是一个抽象类
class Payment(metaclassABCMeta):abstractmethoddef pay(self, money):passclass Alipay(Payment):def pay(self, money): # 这里类的方法不是一致的pay,导致后面调用的时候找不到payprint(支付宝支付了)# 如果子类中没有实现抽象方法实例化对象时就会报错
p Alipay()接口类
from abc import abstractmethod, ABCMetaclass WalkAnimal(metaclassABCMeta):abstractmethoddef walk(self):passclass SwimAnimal(metaclassABCMeta):abstractmethoddef swim(self):passclass FlyAnimal(metaclassABCMeta):abstractmethoddef fly(self):pass# 如果正常一个老虎有跑和跑的方法的话我们会这么做
class Tiger(WalkAnimal, SwimAnimal):def walk(self): passdef swim(self): passt Tiger()如上就不进行解释了。
注意点
注意点
抽象类是一个介于类和接口之间的一个概念同时具备类和接口的部分特性可以用来实现归一化设计。在继承抽象类的过程中我们应该尽量避免多继承而在继承接口的时候我们反而鼓励你来多继承接口 一般情况下 单继承 能实现的功能都是一样的所以在父类中可以有一些简单的基础实现多继承的情况 由于功能比较复杂所以不容易抽象出相同的功能的具体实现写在父类中。