本文共 3657 字,大约阅读时间需要 12 分钟。
反射是Python中的一个强大工具,用于动态操作对象及其属性。它通过四个内置函数:hasattr、getattr、setattr 和 delattr 操作对象,实现对对象属性的查询、获取、设置和删除。这些函数在模块和函数的反射中同样发挥重要作用。
hasattr(object, name) 用于判断对象 object 是否包含名为 name 的属性。其工作原理是调用 getattr(object, name),若抛出 AttributeError,则返回 False,否则返回 True。例如:
class Person(object): def __init__(self, name): self.name = name def talk(self): print('%s正在交谈' % self.name)p = Person('laowang')print(hasattr(p, 'talk')) # 输出 Trueprint(hasattr(p, 'name')) # 输出 Trueprint(hasattr(p, 'abc')) # 输出 False getattr(object, name, default=None) 用于获取对象 object 中的属性或方法,并返回其值。如果属性不存在,且提供了默认值,则返回默认值。例如:
class Person(object): def __init__(self, name): self.name = name def talk(self): print('%s正在交谈' % self.name)p = Person('laowang')name = getattr(p, 'name') # 获取 name 属性的值talk_func = getattr(p, 'talk') # 获取 talk 方法talk_func() # 调用 talk 方法# 若属性不存在,提供默认值s = getattr(p, 'abc', 'not find') # 输出 'not find' setattr(object, name, value) 用于为对象 object 添加或修改属性。例如:
class Person(object): def __init__(self, name): self.name = namep = Person('laowang')setattr(p, 'talk', lambda self: print('%s正在交谈' % self.name)) # 添加 talk 方法setattr(p, 'age', 30) # 添加 age 属性print(p.age) # 输出 30 delattr(object, name) 用于删除对象 object 中的属性。需要注意的是,它不能用于删除方法。例如:
class Foo(object): country = 'china' def __init__(self, name): self.name = nameobj = Foo('abc')delattr(obj, 'name') # 删除 name 属性print(getattr(obj, 'name')) # 输出 AttributeError: 'Foo' object has no attribute 'name'delattr(Foo, 'country') # 删除 country 静态属性print(getattr(Foo, 'country')) # 输出 AttributeError: 'Foo' object has no attribute 'country' 由于 Python 中一切皆对象,模块和函数也可以使用反射机制。例如:
import module_test as objprint(hasattr(obj, 'test')) # 输出 Truegetattr(obj, 'test')() # 输出 'from the test'
对象的某些方法可以通过重定义魔术方法(如 __getattr__、__setattr__、__delattr__ 等)来自定义行为。例如:
class Foo: def __init__(self, x): self.x = x def __getattr__(self, item): print('----> 从 getattr: 你找的属性不存在') def __setattr__(self, key, value): print('----> 从 setattr: 这是尝试设置属性') self.__dict__[key] = value def __delattr__(self, item): print('----> 从 delattr: 这是尝试删除属性') self.__dict__.pop(item)f1 = Foo(10)print(f1.__dict__) # 输出 {'x': 10}f1.z = 3print(f1.__dict__) # 输出 {'x': 10}del f1.aprint(f1.__dict__) # 输出 {'x': 10} __str__ 方法返回用户看到的字符串,__repr__ 返回开发者看到的字符串。例如:
class Student(object): def __init__(self, name): self.name = name def __str__(self): return 'Student object (name: %s)' % self.name __repr__ = __str__s = Student('Michael')print(str(s)) # 输出 'Student object (name: Michael)'print(repr(s)) # 输出 'Student object (name: Michael)' 要使类可以用于 for 循环,需实现 __iter__ 和 __next__ 方法。例如:
class Fib(object): def __init__(self): self.a, self.b = 0, 1 def __iter__(self): return self def __next__(self): self.a, self.b = self.b, self.a + self.b if self.a > 100000: raise StopIteration() return self.afor n in Fib(): print(n)
任何类可以通过定义 __call__ 方法使实例可调用。例如:
class Student(object): def __init__(self, name): self.name = name def __call__(self): print('My name is %s.' % self.name)s = Student('Michael')s() # 输出 'My name is Michael.' __slots__ 用于优化内存使用,限制实例属性仅包含指定字段。例如:
class Foo(object): __slots__ = ['name', 'age']f1 = Foo()f1.name = 'alex'f1.age = 18print(f1.__slots__) # 输出 ['name', 'age']f2 = Foo()f2.name = 'egon'f2.age = 19print(f2.__slots__) # 输出 ['name', 'age']print(Foo.__dict__) # 输出 {} 反射机制在 Python 中非常强大,可以用于动态操作对象属性、模块和函数,以及自定义对象行为。通过合理使用这些功能,可以简化代码,并提高开发效率。
转载地址:http://vxafk.baihongyu.com/