class Father(object): def work(self): print('父亲在工作') class Mather(object): def work(self): print('母亲在工作') class Child(Father, Mather): # 多继承 | 在多继承中, 调用Child的work究竟是继承父类哪一个呢 def __init__(self, name): self._name = name if __name__ == '__main__': c = Child('小明') c.work() # 这里取靠类名最近的 Father | 继承优先级 | 如果自己本身没有这方法 # 打印类的父类结构 继承结构 并按照优先级别排序 # (<class '__main__.Child'>, <class '__main__.Father'>, <class '__main__.Mather'>, <class 'object'>) print(Child.__mro__)
头尾是双下划线的属性或方法, 在Python中是有特殊用途
# 返回这个实例对象的描述 def __str__(self): print(super(Person, self).__str__()) # 父类的结果 print('-' * 80) return ', '.join([ # 该方法只能返回字符串 self.__class__.__module__, # 返回这个类(对象)的模块 self.__class__.__name__, # 返回这个类(对象)的名字 self._name, # 这个实例对象的_name属性 hex(id(self.__class__)), # 这个类(对象)的内存地址 hex: 10进制转16进制字符串 hex(id(self)) # 这个实例对象的内存地址 ]) p = Person('张三') # 重定义后返回 Person 张三 print(p) # <__main__.Person object at 0x0000024E14668F70> | 打印这个对象的描述 调用了 __str__ 方法
from collections.abc import Iterable from collections.abc import Iterator # 斐波拉契数列 class Fib: a = 0 # 定义初始值a b = 1 # 定义初始值b i = 0 # 定义初始值i maxSize = 20 # 定义初始值maxSize # 定义实例对象如何进行转为可迭代对象 __iter__ 必须返回迭代对象 可以for # 默认Person不是可迭代对象 def __iter__(self): return self # 定义实例对象如何进行转为迭代器对象 __next__ def __next__(self): self.i += 1 self.a, self.b = self.b, self.a + self.b # 需要做个判断 否则会死循环 这里没办法中断循环 就只能抛异常 if self.i > self.maxSize: raise StopIteration return self.a f = Fib() print(isinstance(f, Iterable)) # 可迭代对象 print(isinstance(f, Iterator)) # 迭代器对象 for k, _ in enumerate(f): print(str(k).zfill(3), _)
# 定义实例对象可以使用下标形式获取 # 只是感觉有点重复 def __getitem__(self, item): # item可能是下标 也可能切片 a, b, c, i = 1, 1, [], 0 start, stop, step = 0, self.maxSize, 1 if isinstance(item, int): start, stop, step = 0, item, 1 elif isinstance(item, slice): # 切片、范围 (初始, 结束, 步长) | slice(start, stop[, step]) start, stop, step = item.start, item.stop, item.step if start is None: start = 0 if stop is None: start = self.maxSize if step is None: step = 1 # print(start, stop, step) for _ in range(stop): if _ >= start: # print(i) if i % step == 0: c.append(a) i += 1 a, b = b, a + b if isinstance(item, int): return a elif isinstance(item, slice): return c print('-' * 80) # Fib 有点像列表 但还是不能当列表 # 当设置 __getitem__ 后就不报错了 而且获取的值与上面的也对应 可以下标访问 但切片呢?? print(f[5]) # TypeError: 'Fib' object is not subscriptable print(f[5:10:2]) # TypeError: 'slice' object cannot be interpreted as an integer
# 重写这个方法可以时调用不存在的属性或方法不报错 (方法还是会报错) # TypeError: 'NoneType' object is not callable def __getattr__(self, item): # 可能是属性名字 可能是方法名字 prop = '_' + item if prop in self.__dict__: return self.__dict__.get(prop) # 不存在只能当函数调用 防止 TypeError: 'NoneType' object is not callable # 没有方法列表 return lambda: print('%s 方法不存在' % item)
# 把实例对象当成函数调用 __call__ def __call__(self, *args, **kwargs): print('这个实例对象可以当成函数调用') pass # 加上 def __call__(self, *args, **kwargs): 就可以了 # 对象和函数并非那么清晰 print(p()) # TypeError: 'Person' object is not callable
print(callable(p))