什么是反射php
反射的概念是由Smith在1982年首次提出的,主要是指程序能够访问、检测和修改它自己状态或行为的一种能力(自省)。这一律念的提出很快引起了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。java
Python面向对象中的反射python
经过字符串的形式操做对象相关的属性。Python中的一切事物都是对象(均可以使用反射)程序员
四个能够实现自省的函数:app
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():设置属性code
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():删除属性orm
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__)