# 反射 Python 中,反射(Reflection)是一种能力,使得程序能够在运行时查看和修改自身的结构和行为。通过反射,您可以动态地访问和操作类的属性和方法,而无需在编写代码时确定它们的确切名称。这在某些情况下非常有用,例如在框架、库或插件系统中。 ## 对对象的反射 ```python class Foo: f = "类的静态变量" def __init__(self, name, age): self.name = name self.age = age def say_hi(self): print("Hi %s" % self.name) obj = Foo("EaglesLab", 18) # 检测是否含有某属性 print(hasattr(obj, "name")) print(hasattr(obj, "say_hi")) # 获取属性 print(getattr(obj, "name")) func = getattr(obj, "say_hi") func() print(getattr(obj, "job", "不存在啊")) # 报错 # 设置属性 setattr(obj, "job", "teacher") setattr(obj, "show_name", lambda self: self.name + " 真帅") print(obj.__dict__) print(obj.show_name(obj)) # 删除属性 delattr(obj, "age") delattr(obj, "show_name") # delattr(obj,'show_name111') # 不存在,则报错 print(obj.__dict__) ``` ## 对类的反射 ```python class Foo(object): staticField = "test" def __init__(self): self.name = "陈松" def func(self): return "func" @staticmethod def bar(): return "bar" print(getattr(Foo, "staticField")) print(getattr(Foo, "func")) print(getattr(Foo, "bar")) ``` ## 案例:基于反射的用户管理 使用反射前 ```python class User: def login(self): print('欢迎来到登录页面') def register(self): print('欢迎来到注册页面') def save(self): print('欢迎来到存储页面') user = User() while 1: choose = input('>>>').strip() if choose == 'login': user.login() elif choose == 'register': user.register() elif choose == 'save': user.save() ``` 用了反射之后 ```python class User: def login(self): print('欢迎来到登录页面') def register(self): print('欢迎来到注册页面') def save(self): print('欢迎来到存储页面') user = User() while 1: choose = input('>>>').strip() if hasattr(user, choose): func = getattr(user, choose) func() else: print('输入错误...') ``` # 函数 vs 方法 ## 通过打印函数(方法)名确定 ```python def func(): pass print(func) class A: def func(self): pass print(A.func) obj = A() print(obj.func) ``` ## 通过 types 模块验证 ```python from types import FunctionType from types import MethodType def func(): pass class A: def func(self): pass obj = A() print(isinstance(func,FunctionType)) print(isinstance(A.func,FunctionType)) print(isinstance(obj.func,FunctionType)) print(isinstance(obj.func,MethodType)) ``` ## 静态方法是函数 ```python from types import FunctionType from types import MethodType class A: def func(self): pass @classmethod def func1(self): pass @staticmethod def func2(self): pass obj = A() # 静态方法其实是函数 print(isinstance(A.func2,FunctionType)) print(isinstance(obj.func2,FunctionType)) ``` ## 函数与方法的区别 那么,函数和方法除了上述的不同之处,我们还总结了一下几点区别。 1. 函数的是显式传递数据的。如我们要指明为len()函数传递一些要处理数据。 2. 函数则跟对象无关。 3. 方法中的数据则是隐式传递的。 4. 方法可以操作类内部的数据。 5. 方法跟对象是关联的。如我们在用 strip() 方法是,是不是都是要通过 str 对象调用,比如我们有字符串 s,然后 s.strip() 这样调用。是的,strip()方法属于str对象。 我们或许在日常中会口语化称呼函数和方法时不严谨,但是我们心中要知道二者之间的区别。 在其他语言中,如 Java 中只有方法,C 中只有函数,C++ 则取决于是否在类中。 # 双下方法 ## `__init__` 用于初始化类的实例,接收参数并设置实例属性。 ```python class Person: def __init__(self, name, age): self.name = name self.age = age ``` ## `__len__` ```python class B: def __len__(self): return 666 b = B() print(len(b)) # len一个对象就会触发 __len__方法。 class A: def __init__(self): self.a = 1 self.b = 2 def __len__(self): return len(self.__dict__) a = A() print(len(a)) ``` ## `__hash__` ```python 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)) ``` ## `__str__` 如果一个类中定义了 `__str__` 方法,那么在 `print(obj)` 时,默认输出该方法的返回值。 ```python class A: def __init__(self): pass def __str__(self): return '陈松' a = A() print(a) print('%s' % a) ``` ## `__repr__` 如果一个类中定义了 `__repr__` 方法,那么在` repr(obj)` 时,默认输出该方法的返回值。 ```python class A: def __init__(self): pass def __repr__(self): return '陈松' a = A() print(repr(a)) print('%r'%a) ``` ## `__call__` 通过 ` obj() ` 触发执行。 ```python class Foo: def __init__(self): print('__init__') def __call__(self, *args, **kwargs): print('__call__') obj = Foo() # 执行 __init__ obj() # 执行 __call__ ``` ## `__eq__` 通过 `==` 触发类中的 `__eq__` 方法 ```python 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) ``` ## `__del__` 析构方法,当对象在内存中被释放时,自动触发执行。 注:此方法一般无须定义,因为 Python 是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给 Python 解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。 ## `__new__` 在 Python 中,`__new__` 是一个控制对象创建过程的魔术方法,它比 `__init__` 更早执行。 - 优先级:`__new__` 是对象创建的第一步,负责生成实例;`__init__` 是第二步,负责初始化实例。 - 返回值:`__new__` 必须返回实例对象(否则 `__init__` 不会执行),而 `__init__` 无返回值。 - 静态方法:`__new__` 隐式作为静态方法存在,第一个参数是类本身 `cls`,而非实例 `self` - ​​继承链​​:若未重写 `__new__`,Python 会沿继承链调用父类的 `__new__`,直至 `object.__new__` ```python class A: def __new__(cls, *args, **kwargs): print("in new function") return object.__new__(A, *args, **kwargs) # 调用父类的 __new__ 创建实例并返回实例 def __init__(self): self.x = 1 print("in init function") a = A() print(a.x) ```