一、反射    

下述四个函数是专门用来操作类与对象属性的,如何操作?

通过字符串来操作类与对象的属性,这种操作称为反射

class People:
country="China"
def __init__(self,name):
self.name=name
def tell(self):
print('%s is aaa' %self.name) obj=People('egon') 1、hasattr
print(hasattr(People,'country'))
print('country' in People.__dict__) print(hasattr(obj,'name'))
print(hasattr(obj,'country'))
print(hasattr(obj,'tell')) 2、getattr #只有在使用点调用属性且属性不存在的时候才会触发
x=getattr(People,'country1',None)
print(x) f=getattr(obj,'tell',None)#obj.tell
print(f == obj.tell)
f()
obj.tell() 3、setattr
People.x=111
setattr(People,'x',111)
print(People.x) obj.age=18
setattr(obj,"age",18)
print(obj.__dict__) 4、delattr
del People.country
delattr(People,"country")
print(People.__dict__) del obj.name
delattr(obj,"name")
print(obj.__dict__)

  

class Foo:
x=1
def __init__(self,y):
self.y=y def __getattr__(self, item):
print('----> from getattr:你找的属性不存在') def __setattr__(self, key, value):
print('----> from setattr')
# self.key=value #这就无限递归了,你好好想想
# self.__dict__[key]=value #应该使用它 def __delattr__(self, item):
print('----> from delattr')
# del self.item #无限递归了
self.__dict__.pop(item) #__setattr__添加/修改属性会触发它的执行
f1=Foo(10)
print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
f1.z=3
print(f1.__dict__) #__delattr__删除属性的时候会触发
f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__) #__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx

例子

 

  应用实例

class Foo:
def run(self):
while True:
cmd=input('cmd>>: ').strip()
# print('%s run...' %cmd)
if hasattr(self,cmd):
func=getattr(self,cmd)
func() def download(self):
print('download....') def upload(self):
print('upload...') # obj=Foo()
# obj.run()

二、object内置方法

    __str__ 、__del__、__call__等没有设置也是默认就有的,从object类中继承来,不做任何操作,此处是在重写父类方法

  1、__str__()方法 在打印对象时触发     

class People:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex def __str__(self):
# print('========>')
return '<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex) obj=People('egon',18,'male')
print(obj) #执行时相当于print(obj.__str__()) # l=list([1,2,3])
# print(l)

  2、__del__()  析构函数    对象删除时触发

      eg:

       1. del 对象名 删除对象 2. 程序结束释放内存空间时  3. 对象被垃圾回收机制回收时

      在对象被创建时,若有打开文件或手动开辟内存空间等操作,在删除对象,这些系统资源没有被释放,就必须要用__del__方法主动释放内存空间  

              

import time

class People:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex def __del__(self): # 在对象被删除的条件下,自动执行
print('__del__') obj=People('egon',18,'male') del obj #obj.__del__() time.sleep(5)

应用      

class MyOpen:
def __init__(self,filepath,mode="r",encoding="utf-8"):
self.filepath=filepath
self.mode=mode
self.encoding=encoding
self.fobj=open(filepath,mode=mode,encoding=encoding) def __str__(self):
msg="""
filepath:%s
mode:%s
encoding:%s
""" %(self.filepath,self.mode,self.encoding)
return msg def __del__(self):
self.fobj.close() # f=open('a.txt',mode='r',encoding='utf-8') f=MyOpen('aaa.py',mode='r',encoding='utf-8')
# print(f.filepath,f.mode,f.encoding)
# print(f) # print(f.fobj)
res=f.fobj.read()
print(res)

  3、__call__ 方法  调用对象时触发(可用于元类控制类的实例化

class Foo:
def __init__(self):
pass
def __str__(self):
return '123123' def __del__(self):
pass # 调用对象,则会自动触发对象下的绑定方法__call__的执行,
# 然后将对象本身当作第一个参数传给self,将调用对象时括号内的值
#传给*args与**kwargs
def __call__(self, *args, **kwargs):
print('__call__',args,kwargs)

三、元类

  1、cexec()函数

    exec(code , global , local) 将第一个参数code中的代码解析,其中的全局变量以字典形式放到第二个参数global中,局部变量以字典形式放到第三个参数 local中

code="""
global x
x=0
y=2
"""
global_dic={'x':100000}
local_dic={}
exec(code,global_dic,local_dic) print(global_dic)
print(local_dic) code="""
x=1
y=2
def f1(self,a,b):
pass
"""
local_dic={}
exec(code,{},local_dic)
print(local_dic)

  2、一切皆对象,类也是对象,类的类是什么呢?

     类的类就是元类     

我们用class定义的类使用来产生我们自己的对象

内置元类type是用来专门产生class定义的类的

1、用内置的元类type,来实例化得到我们的类

class_name='Chinese'
class_bases=(object,)
class_body="""
country="China"
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def speak(self):
print('%s speak Chinese' %self.name)
"""
class_dic={}
exec(class_body,{},class_dic) 类的三大要素
print(class_name,class_bases,class_dic) Chinese=type(class_name,class_bases,class_dic)
print(Chinese) p=Chinese('egon',18,'male')
print(p.name,p.age,p.sex)

2、自定义元类:

class Mymeta(type):
# 来控制类Foo的创建
def __init__(self,class_name,class_bases,class_dic): #self=Foo
# print(class_name)
# print(class_bases)
# print(class_dic)
if not class_name.istitle():
raise TypeError('类名的首字母必须大写傻叉') if not class_dic.get('__doc__'):
raise TypeError('类中必须写好文档注释,大傻叉') super(Mymeta,self).__init__(class_name,class_bases,class_dic) # 控制类Foo的调用过程,即控制实例化Foo的过程
def __call__(self, *args, **kwargs): #self=Foo,args=(1111,) kwargs={}
# print(self)
# print(args)
# print(kwargs) #1 造一个空对象obj
obj=object.__new__(self) #2、调用Foo.__init__,将obj连同调用Foo括号内的参数一同传给__init__
self.__init__(obj,*args,**kwargs) return obj #Foo=Mymeta('Foo',(object,),class_dic)
class Foo(object,metaclass=Mymeta):
"""
文档注释
"""
x=1
def __init__(self,y):
self.Y=y def f1(self):
print('from f1') obj=Foo(1111) #Foo.__call__() # print(obj)
# print(obj.y)
# print(obj.f1)
# print(obj.x)

单例设计模式:就是只有一个对象的模式,就算是创建多次对象指向的也是同一个对象地址

第一种实现方式:

# 单例模式
import settings class MySQL:
__instance=None
def __init__(self,ip,port):
self.ip=ip
self.port=port @classmethod
def singleton(cls):
if not cls.__instance:
obj=cls(settings.IP, settings.PORT) #setting中的IP 和PORT是固定值
cls.__instance=obj
return cls.__instance # obj4=MySQL(settings.IP,settings.PORT)
# print(obj4.ip,obj4.port) obj4=MySQL.singleton()
obj5=MySQL.singleton()
obj6=MySQL.singleton() print(obj4 is obj5 is obj6)

第二种:通过元类

  

#方式二:定制元类实现单例模式
# import settings
#
# class Mymeta(type):
# def __init__(self,name,bases,dic): #定义类Mysql时就触发
#
# # 事先先从配置文件中取配置来造一个Mysql的实例出来
# self.__instance = object.__new__(self) # 产生对象
# self.__init__(self.__instance, settings.HOST, settings.PORT) # 初始化对象
# # 上述两步可以合成下面一步
# # self.__instance=super().__call__(*args,**kwargs)
#
#
# super().__init__(name,bases,dic)
#
# def __call__(self, *args, **kwargs): #Mysql(...)时触发
# if args or kwargs: # args或kwargs内有值
# obj=object.__new__(self)
# self.__init__(obj,*args,**kwargs)
# return obj
#
# return self.__instance
#
#
#
#
# class Mysql(metaclass=Mymeta):
# def __init__(self,host,port):
# self.host=host
# self.port=port
#
#
#
# obj1=Mysql() # 没有传值则默认从配置文件中读配置来实例化,所有的实例应该指向一个内存地址
# obj2=Mysql()
# obj3=Mysql()
#
# print(obj1 is obj2 is obj3)
#
# obj4=Mysql('1.1.1.4',3307)

第三种: 装饰器

# 方式三:定义一个装饰器实现单例模式
# import settings
#
# def singleton(cls): #cls=Mysql
# _instance=cls(settings.HOST,settings.PORT)
#
# def wrapper(*args,**kwargs):
# if args or kwargs:
# obj=cls(*args,**kwargs)
# return obj
# return _instance
#
# return wrapper
#
#
# @singleton # Mysql=Singleton(Mysql)
# class Mysql:
# def __init__(self,host,port):
# self.host=host
# self.port=port
#
#
#
# obj1=Mysql()
# obj2=Mysql()
# obj3=Mysql()
# print(obj1 is obj2 is obj3) #True
#
# obj4=Mysql('1.1.1.3',3307)
# obj5=Mysql('1.1.1.4',3308)
# print(obj3 is obj4) #Fals

作业:    

'''
4-17日作业
'''
'''
1、判断一个对象是否属于str类型,判断一个类是否是另外一个类的子类
'''
a='123'
print(isinstance(a,str))
print(issubclass(str,object)) '''
2、有俩程序员,一个lili,一个是egon,lili在写程序的时候需要用到egon所写的类(放到了另外一个文件中),但是egon去跟女朋友度蜜月去了,还没有完成他写的类,
class FtpClient:
"""
ftp客户端,但是还么有实现具体的功能
"""
def __init__(self,addr):
print('正在连接服务器[%s]' %addr)
self.addr=addr 此处应该完成一个get功能
lili想到了反射,使用了反射机制lili可以继续完成自己的代码,等egon度蜜月回来后再继续完成类的定义并且去实现lili想要的功能。
''' class FtpClient:
"""
ftp客户端,但是还么有实现具体的功能
""" def __init__(self, addr):
print('正在连接服务器[%s]' % addr)
self.addr = addr
f=FtpClient('egon')
addr=getattr(f,'addr')
print(addr) ''' 3、定义一个老师类,定制打印对象的格式为‘<name:egon age:18 sex:male>’
'''
class Teacher:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def __str__(self):
return '<name: %s age: %s sex: %s>'%(self.name,self.age,self.sex)
t=Teacher('egon',18,'male')
print(t) '''
4、定义一个自己的open类,控制文件的读或写,在对象被删除时自动回收系统资源
'''
class MyOpen:
def __init__(self,file,io,encoding):
self.file=file
self.io=io
self.encoding=encoding
self.my_open=open(self.file,self.io,encoding=self.encoding)
def __del__(self):
self.my_open.close()
print('guan bi wen jian') mo=MyOpen(r'F:\python\object\days2\days23\setting.py','rt','utf-8')
del mo '''
5、自定义元类,把自定义类的数据属性都变成大写,必须有文档注释,类名的首字母必须大写
'''
class Mymeta(type):
def __init__(self,class_name,class_base,class_dict):
dict={}
for name in class_dict:
if not name.istitle():
new_name=name.capitalize()
dict.update({new_name:class_dict[name]})
print(dict)
super().__init__(class_name,class_base,dict)
if not class_name.istitle():
raise TypeError('类名必须首字母大写')
if not class_dict.get('__doc__'):
raise TypeError('类必须有文档注释')
class My(object,metaclass=Mymeta):
'''
MY 1233123
'''
char='123'
def abc(self):
print(self.char)
m=My()
print(My.__dict__) ''' 6、用三种方法实现单例模式,参考答案:http://www.cnblogs.com/linhaifeng/articles/8029564.html#_label5
''' class Mymeta(type):
__obj = ''
def __call__(self, *args, **kwargs):
if self.__obj=='':
self.__obj=self.__new__(self)
self.__obj.__init__(*args, **kwargs)
return self.__obj
class My(object,metaclass=Mymeta):
'''
MY 1233123
'''
char='123'
def abc(self):
print(self.char)
m = My()
m2 = My()
m3 = My()
print(m, m2, m3)

    

4月17日 python学习总结 反射、object内置方法、元类的更多相关文章

  1. python 面向对象之反射及内置方法

    面向对象之反射及内置方法 一.静态方法(staticmethod)和类方法(classmethod) 类方法:有个默认参数cls,并且可以直接用类名去调用,可以与类属性交互(也就是可以使用类属性) 静 ...

  2. python面向对象之反射和内置方法

    一.静态方法(staticmethod)和类方法(classmethod) 类方法:有个默认参数cls,并且可以直接用类名去调用,可以与类属性交互(也就是可以使用类属性) 静态方法:让类里的方法直接被 ...

  3. python基础之反射内置方法元类

    补充内置函数 isinstance(obj,Foo)   # 判断obj是不是foo的实例 issubclass()      # 判断一个类是不是另一个类的子类 反射 什么是反射? 通过字符串来操作 ...

  4. python学习day7 数据类型及内置方法补充

    http://www.cnblogs.com/linhaifeng/articles/7133357.html#_label4 1.列表类型 用途:记录多个值(一般存放同属性的值) 定义方法 在[]内 ...

  5. Python学习之路8 - 内置方法

    abs(-230) #取绝对值 all([0,1,-5]) #如果参数里面的所有值都为真就返回真,否则返回假 any([0,1,-5]) #如果参数里面有一个值为真则返回真,否则返回假 ascii([ ...

  6. Python反射和内置方法(双下方法)

    Python反射和内置方法(双下方法) 一.反射 什么是反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发 ...

  7. day31 反射,内置方法,元类

    目录 一.反射 1 什么是反射 2 如何实现反射 二.内置方法 1 什么是内置方法 2 为什么要用内置方法 3 如何使用内置方法 3.1 str 3.2 del 三.元类 1 什么是元类 2 clas ...

  8. Learning-Python【26】:反射及内置方法

    反射的概念 可以用字符串的方式去访问对象的属性,调用对象的方法(但是不能去访问方法),Python 中一切皆对象,都可以使用反射. 反射有四种方法: hasattr:hasattr(object, n ...

  9. 面向对象(五)——isinstance与issubclass、反射、内置方法

    isinstance与issubclass.反射.内置方法 一.isinstance与issubclass方法 1.isinstance是用来判断对象是否是某个类 isinstance(obj,cla ...

随机推荐

  1. 第8章 File I/O,File类操作文件的属性

    1.文件 1.1.什么是文件? 答:文件可认为是相关记录或放在一起的数据的集合 1.2.文件- -般存储在哪里? 答: 磁盘,硬盘,文件夹 1.3.JAVA程序如何访向文件属性? JAVA API:i ...

  2. suse 12 二进制部署 Kubernetets 1.19.7 - 第06章 - 部署kube-apiserver组件

    文章目录 1.6.部署kube-apiserver 1.6.0.创建kubernetes证书和私钥 1.6.1.生成kubernetes证书和私钥 1.6.2.创建metrics-server证书和私 ...

  3. Linux系统安装tomcat9服务(含jdk的安装)

    使用虚拟机上CentOS8系统. 1.安装tomcat的依赖jdk版本11 将jdk11解压至相应目录: 设置环境变量: 末尾添加: 更新配置文件: 验证: 补充使用yum安装jdk的方式: 1)查看 ...

  4. kube-proxy的三种工作模式

    kube-proxy模式详解 kubernetes里kube-proxy支持三种模式,在v1.8之前我们使用的是iptables 以及 userspace两种模式,在kubernetes 1.8之后引 ...

  5. 实际项目中使用CompletionService提升系统性能的一次实践

    随着互联网应用的深入,很多传统行业也都需要接入到互联网.我们公司也是这样,保险核心需要和很多保险中介对接,比如阿里.京东等等.这些公司对于接口服务的性能有些比较高的要求,传统的核心无法满足要求,所以信 ...

  6. 超简单集成华为 HMS MLKit 机器学习服务:银行卡识别 SDK,一键实现银行卡绑定

    前言 小编前面几期文章分别给大家介绍了使用 HMS ML Kit SDK 实现微笑抓拍.证件照 DIY.拍照翻译的功能开发(链接见文章末尾),本次小编给大家带来的是使用 HMS 机器学习服务(ML K ...

  7. 昨天面试被问到的 缓存淘汰算法FIFO、LRU、LFU及Java实现

    缓存淘汰算法 在高并发.高性能的质量要求不断提高时,我们首先会想到的就是利用缓存予以应对. 第一次请求时把计算好的结果存放在缓存中,下次遇到同样的请求时,把之前保存在缓存中的数据直接拿来使用. 但是, ...

  8. wmware15安装centos7.9

    详细步骤如下: 下面位置应该写:D:\k8s\k8s-master01 也可以桥接 下面可以删除 从官方下载的,不需要test,所以选择第一个 默认英文的即可 改为上海 保持默认 配置静态ip 主机名 ...

  9. HMS Core在MWC2022展示最新开放能力,助力开发者构建精品应用

    [2022年2月28日,巴塞罗那]世界移动通信大会MWC2022在巴塞罗那开幕.HMS Core设立了3个展台(Fira Gran Via,Hall 1),向全球开发者展示HMS Core 6的全新开 ...

  10. Web应用程序攻击和检查框架w3af

    实验目的 利用w3af爬虫插件探测出目标网站的目录结构. 实验原理 1) W3AF是一个web应用安全的攻击.审计平台,通过增加插件来对功能进行扩展.这是一款用python写的工具,可以查看所有源代码 ...