Python反射和内置方法(双下方法)
Python反射和内置方法(双下方法)
一、反射
什么是反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
Python面向对象中的反射
通过字符串的形式操作对象相关的属性。Python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数:
hasattr():检测是否含有某属性
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age def func(self):
pass # 检测是否含有某属性
print(hasattr(Foo, "func")) # True
f = Foo("dogfa", 18)
print(hasattr(f, "name")) # True
print(hasattr(f, "gender")) # False
getattr():获取属性
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age def func(self):
pass @staticmethod
def staticfunc():
print("嘿嘿嘿") # 获取属性
f = getattr(Foo, "staticfunc")
print(f) # <function Foo.staticfunc at 0x0000028DD8EB9D08>
f() # 嘿嘿嘿 # 如果要获取的属性不存在那么就会报错
f2 = getattr(Foo, "func1") # AttributeError: type object 'Foo' has no attribute 'func1'
setattr():设置属性
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age def func(self):
pass @staticmethod
def staticfunc():
print("嘿嘿嘿") f = Foo("dogfa", 18)
print(f.__dict__) # {'name': 'dogfa', 'age': 18}
setattr(f, "name", f.name + "sb")
print(f.__dict__) # {'name': 'dogfa_sb', 'age': 18}
defattr():删除属性
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age def func(self):
pass @staticmethod
def staticfunc():
print("嘿嘿嘿") f = Foo("dogfa", 18)
print(f.__dict__) # {'name': 'dogfa', 'age': 18}
delattr(f, "name")
print(f.__dict__) # {'age': 18} # delattr(f, "gender") # 删除不存在的属性时会报错
使用反射的场景
- 对对象的反射
- 对类的反射
- 其它模块的反射
- 当前模块的反射
二、内置方法
函数与方法的区别
在说方法之前我们先来说一下在Python中函数和方法的区别。
# 通过导入types模块来验证
from types import FunctionType, MethodType def func():
pass class A:
def func(self):
pass @staticmethod
def func2():
pass obj = A() # FunctionType:函数 MethodType:方法
print(isinstance(func, FunctionType)) # True
print(isinstance(A.func, FunctionType)) # True
print(isinstance(obj.func, FunctionType)) # False
print(isinstance(obj.func, MethodType)) # True
print(isinstance(A.func2, FunctionType)) # True
print(isinstance(obj.func2, FunctionType)) # True # 通过打印函数(方法)名验证
from types import FunctionType, MethodType
def func():
pass class A:
def func(self):
pass @staticmethod
def func2():
pass obj = A() print(func) # <function func at 0x000002013BC32E18>
print(A.func) # <function A.func at 0x000002013BF6A598>
print(obj.func) # <bound method A.func of <__main__.A object at 0x000002013BDF7DD8>>
总结:
(1)函数的是显式传递数据的。如我们要指明为len()函数传递一些要处理数据。
(2)函数则跟对象无关。
(3)方法中的数据则是隐式传递的。
(4)方法可以操作类内部的数据。
(5)方法跟对象是关联的。如我们在用strip()方法时,都是要通过str对象调用,比如我们有字符串s,然后s.strip()这样调用。是的,strip()方法属于str对象。
(6)静态方法就是函数
内置方法(双下方法)
定义:双下方法是特殊方法,他是解释器提供的 由爽下划线加方法名加双下划线 __方法名__的具有特殊意义的方法,双下方法主要是Python源码程序员使用的,我们在开发中尽量不要使用双下方法,但是深入研究双下方法,更有益于我们阅读源码。
调用:不同的双下方法有不同的触发方式,就好比盗墓时触发的机关一样,不知不觉就触发了双下方法,例如:__init__
item系列
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age def __getitem__(self, item):
print("执行obj['key']时会执行我")
return getattr(self, item) def __setitem__(self, key, value):
print("执行obj['key'] = value 时会执行我")
setattr(self, key, value) def __delitem__(self, key):
print("执行del['key']时会执行我")
delattr(self, key) obj = Foo("oldwang", 20)
print(obj["name"])
# 执行obj['key']时会执行我
# oldwang obj["name"] = "oldniu"
print(obj["name"])
# 执行obj['key'] = value 时会执行我
# 执行obj['key']时会执行我
# oldniu print(obj.__dict__)
del obj["name"]
print(obj.__dict__)
# {'name': 'oldniu', 'age': 20}
# 执行del['key']时会执行我
# {'age': 20}
__del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
class FileHandle:
def __init__(self, file_path):
self.f = open(file_path, mode="r", encoding="utf-8") def read(self):
return self.f.read(1024) def __del__(self):
# 在程序执行完时释放文件句柄
self.f.close() f = FileHandle("file/userinfo")
print(f.read())
__new__
# 单例类
class Single:
__isinstance = None def __new__(cls, *args, **kwargs):
if not cls.__isinstance:
cls.__isinstance = object.__new__(cls)
return cls.__isinstance
return cls.__isinstance one = Single()
two = Single()
print(one is two) # True
__call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 call 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo:
def __call__(self, *args, **kwargs):
print("执行__call__") f = Foo()
f() # 执行__call__ # 还可以这样写
Foo()()
__len__
class Foo:
def __init__(self, name, age):
self.name = name
self.age =age def __len__(self):
return len(self.__dict__) f = Foo("dogfa", 18)
print(len(f)) # 2
__hash__
class A:
def __init__(self):
self.a = 1
self.b = 2 def __hash__(self):
return hash(str(self.a)+str(self.b))
a = A()
print(hash(a))
__eq__
class A:
def __init__(self):
self.a = 1
self.b = 2 def __eq__(self,obj):
if self.a == obj.a and self.b == obj.b:
return True
a = A()
b = A()
print(a == b) # True
三、其它
# 有一个员工类,1000个员工对象,对象属性有姓名,性别,年龄,部门,
# 按姓名,性别对1000个对象去重
class Employee:
def __init__(self, name, age, gender, department):
self.name = name
self.age = age
self.gender = gender
self.department = department
def __hash__(self):
return hash("{0}{1}".format(self.name, self.gender))
def __eq__(self, other):
if self.name == other.name and self.gender == other.gender:
return True
employee_list = []
for i in range(250):
employee_list.append(Employee("dogfa", i, "male", "python" + str(i)))
for i in range(250):
employee_list.append(Employee("djb", i, "female", "php" + str(i)))
for i in range(250):
employee_list.append(Employee("oldniu", i, "male", "java" + str(i)))
for i in range(250):
employee_list.append(Employee("cdj", i, "female", "go" + str(i)))
for employee_obj in set(employee_list):
print(employee_obj.__dict__)
Python反射和内置方法(双下方法)的更多相关文章
- python 反射和内置方法
一.isinstance和issubclass class Foo: pass class Son(Foo): pass s = Son() #判断一个对象是不是这个类的对象,传两个参数(对象,类) ...
- Python day12部分内置函数的常见方法
#内置函数 print(abs(-1))#绝对值 ']))#判断list的真假,都真则真,有一个假也是假 print(any(''))#有一个真就真,全假则假 print(bin(3))#十进制转换二 ...
- Python面向对象之魔法方法/双下方法
1.__new__ and __init__ 这两个方法都是在实例化的时候执行,__new__ 在 __init__ 之前执行,并且 如果实例化的时候封装属性,__new__也是必须要传的,而且__n ...
- day27:反射和双下方法
1, # 面向对象的三大特性:继承,多态和封装 # 继承: # 单继承: **** # 父类(超类,基类) # 子类(派生类) 派生方法和派生属性 # 子类的对象在调用方法和属性:先用自己的,自己没有 ...
- python面向对象 : 反射和内置方法
一. 反射 1. isinstance()和issubclass() isinstance( 对象名, 类名) : 判断对象所属关系,包括父类 (注:type(对象名) is 类名 : 判断对象所属 ...
- Python面向对象之反射,双下方法
一. 反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序 ...
- 反射,内置方法,__str__ __repr__
反射 反射用到的mmp模块 def wahaha():print('wahaha') class QQxing: def __init__(self,name): self.name = name d ...
- python之路-双下方法
双下方法 定义: 双下方法是特殊方法,他是解释器提供的,由双下线加方法名加双下划线 __方法名__具有特殊意义的方法 双下方法主要是Python源码程序员使用的,元编程 我们在开发中尽量不要使用双下方 ...
- Python面向对象 | 双下方法
定义:双下方法是特殊方法,他是解释器提供的.由双下划线+方法名+双下划线 .它具有特殊意义的方法,双下方法主要是python源码程序员使用的,我们在开发中尽量不要使用双下方法,但是深入研究双下方法,更 ...
随机推荐
- hdu2476(区间dp+dp)
String painter Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- BZOJ2716天使玩偶
不会KD-tree怎么办?CQD硬搞. 建立正常的平面直角坐标系,首先我们只考虑在目标点左下角的点对目标点的贡献,由于左下点的横纵坐标都小于目标点,那么曼哈顿距离就可以化简了,绝对值去掉后,得到$x2 ...
- Java 多线程编程(锁优化)
转:https://mp.weixin.qq.com/s/lDuguEhuWiLY8ofBRy3tZA 并发环境下进行编程时,需要使用锁机制来同步多线程间的操作,保证共享资源的互斥访问. 加锁会带来性 ...
- Java的反射是什么?有什么用?
首先我要简单的来说一下什么是Java的反射机制: 在Java里面一个类有两种状态--编译和运行状态,通常我们需要获取这个类的信息都是在编译阶段获得的,也就是直接点出来或者new出来,可是如果需要在类运 ...
- 详解JDBC对象
1. DriverManager (1) 注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); 真正注册驱动的是驱动包下 jdbc 文件夹 ...
- Oracle虚拟机 与 windows配置
目录 相关资料 安装虚拟机及相关配置 安装PLSQL Developer Navicat Premium登录数据库 踩坑之路 相关资料 oracle虚拟机配置 提取码:s3sg 安装虚拟机及相关配置 ...
- golang基于当前1.9版本进行源码编译升级到1.10
一.起因 golang出了最新的1.10版本,而刚出的vgo也是需要基于该最新版本的.为了测试vgo,因此需要将我的v1.9升级到v1.10版本. 安装过golang的同学都知道,golang常用的有 ...
- Windows服务器下,Tomcat制作成服务自启动,跑不起来,报内存溢出。
测试过不行 使用服务启动后,tomcat运行时会抛出各种内存溢出错误,于是我第一时间想到的是去修改catalina.bat文件中的内存设置,但是然并卵,于是我又尝试不用服务,去使用startup.ba ...
- HTML Button自动刷新页面的问题
一.问题<button class="am-btn am-btn-default am-btn-xs am-text-secondary" data-id="99& ...
- ISO/IEC 9899:2011 条款6.2.4——对象的存储持久性
6.2.4 对象的存储持久性 1.一个对象具有一个存储持久性来确定其生命周期.一共有四种存储持久性:静态的,线程的,自动的,以及分配的.分配存储在7.22.3中描述. 2.一个对象的生命周期是程序执行 ...