python 面向对象进阶之对象内置方法
反射相关
常用的就是hasattr,getattr
class A(): def __init__(self): pass def func(self): print("func") a = A() a.name = "123" a.age = 123 print(getattr(a,"name")) getattr(a, "func")() print(hasattr(a, "ame"))
setattr,delattr,用于设置变量和删除变量,不常用
用于对象的一些内置方法:
__str__
调用对象,自动输出
class B: def __str__(self): return 'str : class B' def __repr__(self): return 'repr : class B' b = B() print('%s' % b) print('%r' % b)
__getitem__, __setitem__, __delitem__
用于索引操作,如字典。以上分别表示获取、设置、删除数据
class C(object):
def __init__(self): self.value = {} self.name = 'test' def __getitem__(self, item): print '__getitem__', item return self.value[item] def __setitem__(self, key, value): print '__setitem__', key, value self.value[key] = value def __delitem__(self, key): print '__delitem__', key del self.value[key] def __len__(self): return len(self.value) print C.__doc__ c = C() #print c #result = c['k1'] c['k2'] = 5 c['k1'] = "Hello" print c['k2'] print len(c)
__call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('__call__') obj = Foo() # 执行 __init__ obj() # 执行 __call__
__hash__
外部哈希,依赖与内置__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, name): self.name = name def __eq__(self, other): if (self.__dict__ == other.__dict__): return True a = A("test") b = A("test") print(a == b)
set()对象去重,依赖于hash,eq方法
class Person: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def __hash__(self): return hash(self.name+self.sex) def __eq__(self, other): if self.name == other.name and self.sex == other.sex:return True p_lst = [] for i in range(84): p_lst.append(Person('egon',i,'male')) print(p_lst) print(set(p_lst))
__del__()
方法
创建对象后,python解释器默认调用__init__()
方法;
当删除一个对象时,python解释器也会默认调用一个方法,这个方法为__del__()
方法
import time class Animal(object): # 初始化方法 # 创建完对象后会自动被调用 def __init__(self, name): print('__init__方法被调用') self.__name = name # 析构方法 # 当对象被删除时,会自动被调用 def __del__(self): print("__del__方法被调用") print("%s对象马上被干掉了..."%self.__name) # 创建对象 dog = Animal("哈皮狗") # 删除对象 del dog cat = Animal("波斯猫") cat2 = cat cat3 = cat print("---马上 删除cat对象") del cat print("---马上 删除cat2对象") del cat2 print("---马上 删除cat3对象") del cat3 print("程序2秒钟后结束") time.sleep(2)
结果:
总结
- 当有1个变量保存了对象的引用时,此对象的引用计数就会加1
- 当使用del删除变量指向的对象时,如果对象的引用计数不会1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除
__slots__
现在我们终于明白了,动态语言与静态语言的不同
动态语言:可以在运行的过程中,修改代码
静态语言:编译时已经确定好代码,运行过程中不能修改
如果我们想要限制实例的属性怎么办?比如,只允许对Person实例添加name和age属性。
为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:
>>> class Person(object): __slots__ = ("name", "age") >>> P = Person() >>> P.name = "老王" >>> P.age = 20 >>> P.score = 100 Traceback (most recent call last): File "<pyshell#3>", line 1, in <module> AttributeError: Person instance has no attribute 'score' >>>
注意:
- 使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
In [67]: class Test(Person): ...: pass ...: In [68]: t = Test() In [69]: t.score = 100