精选文章 反射、元类

反射、元类

作者:aoni3517 时间: 2021-02-07 01:33:51
aoni3517 2021-02-07 01:33:51
【摘要】一、补充内置函数 1.  isinstance(obj,cls):检测object是否是cls的对象 class Foo(object): pass obj = Foo() isinstance(obj, Foo 在python3中统一类与类型的概念 d={'x':1} #d=dict({'x':1} #) print(type(d) is dict) print(isinstance(d,...
一、补充内置函数
1. isinstance(obj,cls):检测object是否是cls的对象
class Foo(object):
pass

obj = Foo()

isinstance(obj, Foo


在python3中统一类与类型的概念
d={'x':1} #d=dict({'x':1} #)

print(type(d) is dict)
print(isinstance(d,dict))



2. issubclass(sub,super):检查sub类是否是super类的派生类

class Foo(object):
pass

class Bar(Foo):
pass

issubclass(Bar, Foo)


二、反射
1.什么是反射:通过字符串来操作类或者对象的属性
2.如何用:
hasattr:判断object中有没有一个name字符串对应的方法或属性
getattr:获取
setattr:设置
delattr:删除

class People:
country='China'
def __init__(self,name):
self.name=name

def eat(self):
print('%s is eating' %self.name)

peo1=People('egon')

print(hasattr(peo1,'eat')) #peo1.eat
print(getattr(peo1,'eat')) #peo1.eat
print(getattr(peo1,'xxx',None))

setattr(peo1,'age',18) #peo1.age=18
print(peo1.age)

print(peo1.__dict__)
delattr(peo1,'name') #del peo1.name
print(peo1.__dict__)

例子:
class Ftp:
def __init__(self,ip,port):
self.ip=ip
self.port=port

def get(self):
print('GEY function')

def put(self):
print('PUT function')

def run(self):
while True:
choice=input('>>>:').strip()
# if hasattr(self,choice):
# method=getattr(self,choice)
# method()
# else:
# print('输入指令不存在')

method=getattr(self,choice,None)
if method:
method()
else:
print('输入指令不存在')

conn=Ftp('11.11.2',11)
conn.run()


三、自定义内置方法来定制类的功能
1. __str__方法

class People:
def __init__(self,name,age):
self.name=name
self.age=age

#在对象被打印时,自动触发,应该在该方法内采集与对象self有关的信息,然后拼成字符串返回
def __str__(self):
return '' %(self.name,self.age)
obj=People('egon',18)
obj1=People('alex',18)
print(obj) #obj.__str__()
print(obj1) #obj1.__str__()

2. __del__析构方法:
__del__会在对象被删除之前自动触发
class People:
def __init__(self,name,age):
self.name=name
self.age=age
self.f=open('a.txt','rt',encoding='utf-8')

def __del__(self):
# print('run=-====>')
# 做回收系统资源相关的事情

self.f.close()

obj=People('egon',18)

print('主')


四、元类
1、什么是元类
在python中一切皆对象,那么我们用class关键字定义的类本身也是一个对象
负责产生该对象的类称之为元类,即元类可以简称为类的类
class Foo:#Foo=元类()
pass

2、为何要用元类
元类是负责产生类的,所以我们学习元类或者自定义元类的目旳是为了
控制类的产生过程,还可以控制对象的产生过程

3、如何用元类


1.储备知识:内置函数exec的用法
cmd="""
x=1
def func(self):
pass
"""
class_dic={}
exec(cmd,{},class_dic)

print(class_dic)
exec 会将执行cmd,将其产生的名称空间放入class_dic

2.创建类的方法有两种
大前提:如果说类也是对象的话,那么用class关键字的去创建类的过程也是一个实例化的过程
该实例化的目的是为了得到一个类,调用的是元类

2.1方式一:用的默认的元类type

class People: #People=type(...)
country='China'
def __init__(self,name,age):
self.name=name
self.age=age

def eat(self):
print('%s is eating' %self.name)

print(type(People))

2.1.1 创建类的3个要素:类名,基类,类的名称空间
class_name='People'
class_bases=(object,)
class_dic={}
class_body="""
country='China'
def __init__(self,name,age):
self.name=name
self.age=age

def eat(self):
print('%s is eating' %self.name)
"""
exec(class_body,{},class_dic)

准备好创建类的三要素

print(class_name)
print(class_bases)
print(class_dic)

People=type(类名,基类,类的名称空间)
People1=type(class_name,class_bases,class_dic)
print(People1)
obj1=People1('egon',18)
print(People)
obj=People('egon',18)

obj1.eat()
obj.eat()


2.2 方式二:用的自定义的元类
class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
def __init__(self,class_name,class_bases,class_dic):
#print(self) #现在是People
#print(class_name)
#print(class_bases)
#print(class_dic)
super(Mymeta,self).__init__(class_name,class_bases,class_dic) #重用父类的功能

# 分析用class自定义类的运行原理(而非元类的的运行原理):
#1、拿到一个字符串格式的类名class_name='People'
#2、拿到一个类的基类们class_bases=(object,)
#3、执行类体代码,拿到一个类的名称空间class_dic={...}
#4、调用People=type(class_name,class_bases,class_dic)
class People(object,metaclass=Mymeta): #People=Mymeta(类名,基类们,类的名称空间)
country='China'
def __init__(self,name,age):
self.name=name
self.age=age

def eat(self):
print('%s is eating' %self.name)


应用:自定义元类控制类的产生过程,类的产生过程其实就是元类的调用过程


class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
def __init__(self,class_name,class_bases,class_dic):
if class_dic.get('__doc__') is None or len(class_dic.get('__doc__').strip()) == 0:
raise TypeError('类中必须有文档注释,并且文档注释不能为空')
if not class_name.istitle():
raise TypeError('类名首字母必须大写')
super(Mymeta,self).__init__(class_name,class_bases,class_dic) #重用父类的功能

class People(object,metaclass=Mymeta): #People=Mymeta('People',(object,),{....})
"""这是People类"""
country='China'
def __init__(self,name,age):
self.name=name
self.age=age

def eat(self):
print('%s is eating' %self.name)





3、储备知识:__call__
class Foo:
def __call__(self, *args, **kwargs):
print(self)
print(args)
print(kwargs)


obj=Foo()

要想让obj这个对象变成一个可调用的对象,需要在该对象的类中定义一个方法__call__方法
该方法会在调用对象时自动触发
obj(1,2,3,x=1,y=2)

4、自定义元类来控制类的调用的过程,即类的实例化过程

class Mymeta(type):

def __call__(self, *args, **kwargs):
# print(self) # self是People
# print(args)
# print(kwargs)
# return 123

# 1、先造出一个People的空对象
obj=self.__new__(self)
# 2、为该对空对象初始化独有的属性
# print(args,kwargs)
self.__init__(obj,*args,**kwargs)

# 3、返回一个初始好的对象
return obj


class People(object,metaclass=Mymeta):
country='China'
def __init__(self,name,age):
self.name=name
self.age=age

def eat(self):
print('%s is eating' %self.name)

#def __new__(cls, *args, **kwargs):
#print(cls)
## cls.__new__(cls) # 错误
#obj=super(People,cls).__new__(cls)
# return obj

分析:调用People的目的
1、先造出一个People的空对象
2、为该对空对象初始化独有的属性
# obj1=People('egon1',age=18)
# obj2=People('egon2',age=18)
# print(obj1)
# print(obj2)

obj=People('egon',age=18)
print(obj.__dict__)
print(obj.name)
obj.eat()







转载于:https://www.cnblogs.com/kingyanan/p/9248765.html

勿删,copyright占位
分享文章到微博
分享文章到朋友圈

上一篇:面相对象初始

下一篇:hashcode()与equals()方法(第8周)

您可能感兴趣

  • 解决VC中增加类文件的问题

    解决VC中增加类文件的问题  一、通过“AddToProject”向当前工作区A增加DibDoc类头文件及应用文件,在A的类A1中使用DibDoc类后编译,出现如下错误:  errorC2501:'CDibdoc':missing dec1-specifiers  于是作了以下处理,解决了出现的问题:  1.检查发现在类A1中,头文件包含#include"dibdoc.h"放在了#inclu...

  • Java数 据 类 型

    § 2.1数 据 类 型数 据 类 型 指 明 了 变 量 或 表 达 式 的 状 态 和 行 为 。 Java的 数据 类 型 如 下 所 示 :Java不 支 持 C、 C++中 的 指 针 类 型、结 构 体 类 型 和 共 用 体 类 型。本 章 我 们 主 要 介 绍 简 单 类 型 。§ 2.2常 量 与 变 量一 、 常 量Java中 的 常 量 值 是 用 文 字 串 表 示...

  • UML参考手册 第 四 部 分  附 录 附录 UML元模

    UML参考手册    第 四 部 分  附 录   附录 UML元模   1.UML定义文档(UML Definition Documents)  UML 由一系列Object Management Group[UML-98]出版的文档定义。这些文档包含在本书所附的CD中。本章解释在这些文档描述的UML语义模型的结构。UML使用元模型正式定义——也就是说,UML中的构成物的模型。元模型本身...

  • .NET框架类览胜(下篇)(1)

    .NET框架类览胜(下篇)(1) [ 作者: 不详 添加时间: 2001-5-30 8:11:13 ]![一、处理字符串 .NET 框架类(或System类)提供了大量可在构造.NET应用时使用的核心功能,这些功能适用于任何语言环境。本文的第一部分介绍了程序集、名称空间等基本概念以及System.Math和System.Random类。这是本文的第二部分,接着讨论其他几个很有用的类:Sys...

  • .NET框架类览胜(上篇)(1)

    .NET框架类览胜(上篇)(1) [ 作者: 松下客 添加时间: 2001-5-30 8:09:43 ] ![一、基本概念 .NET框架(Framework)是一个开发、部署和运行.NET应用的环境,包括了ASP.NET、公共语言运行时环境(CLR)以及.NET 框架类。关于ASP.NET和CLR的介绍已经有很多,相对而言,关于.NET框架类的介绍却比较少见。 .NET框架类也即Syste...

  • C++中类及类的定义

    在面向对象的程序设计中,有经常接触类、对象等专业名词;到底什么是类、什么是对象呢?在程序又是怎样运用呢?类是面向对象程序设计的核心,它实际是一种新的数据类型,也是实现抽象类型的工具,因为类是通过抽象数据类型的方法来实现的一种数据类型。类是对某一类对象的抽象;而对象是某一种类的实例,因此,类和对象是密切相关的。没有脱离对象的类,也没有不依赖于类的对象。    什么是类    类是一种复杂的数据...

  • 初始化C++类成员和在你的MFC应用中的加入位置

    问题  我的问题是关于初始化C++类成员的。我见过许多这样的代码(包括在你的栏目中也见到过): CSomeClass::CSomeClass() {     x=0;     y=1; } 而在别的什么地方则写成下面的样子: CSomeClass::CSomeClass() : x(0), y(1) { } 我的一些程序员朋友说第二种方法比较好,但他们都不知道为什么是这样。你能告诉我这两种类...

  • delete this,dll导出类及如何写plugins(PART II)

    2.dll导出类的几种方法。其实我就知道两种啦,还请大家补充。先看M$使用的方法。struct exports{__declspec(dllexport)exports();__declspec(dllexport)~exports();};exports::exports(){}exports::~exports(){}优点:完全和本地的类一样使用,可以直接new/delete.缺点:只能...

CSDN

CSDN

中国开发者社区CSDN (Chinese Software Developer Network) 创立于1999年,致力为中国开发者提供知识传播、在线学习、职业发展等全生命周期服务。

华为云40多款云服务产品0元试用活动

免费套餐,马上领取!
反射、元类介绍:华为云为您免费提供反射、元类在博客、论坛、帮助中心等栏目的相关文章,同时还可以通过 站内搜索 查询更多反射、元类的相关内容。| 移动地址: 反射、元类 | 写博客